[ Index ]

MailPress 7.2

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]     [ Statistics ]    

title

Body

[close]

/mp-includes/composer/vendor/swiftmailer/swiftmailer/doc/ -> plugins.rst (source)

   1  Plugins
   2  =======
   3  
   4  Plugins exist to extend, or modify the behaviour of Swift Mailer. They respond
   5  to Events that are fired within the Transports during sending.
   6  
   7  There are a number of Plugins provided as part of the base Swift Mailer package
   8  and they all follow a common interface to respond to Events fired within the
   9  library. Interfaces are provided to "listen" to each type of Event fired and to
  10  act as desired when a listened-to Event occurs.
  11  
  12  Although several plugins are provided with Swift Mailer out-of-the-box, the
  13  Events system has been specifically designed to make it easy for experienced
  14  object-oriented developers to write their own plugins in order to achieve
  15  goals that may not be possible with the base library.
  16  
  17  AntiFlood Plugin
  18  ----------------
  19  
  20  Many SMTP servers have limits on the number of messages that may be sent during
  21  any single SMTP connection. The AntiFlood plugin provides a way to stay within
  22  this limit while still managing a large number of emails.
  23  
  24  A typical limit for a single connection is 100 emails. If the server you
  25  connect to imposes such a limit, it expects you to disconnect after that number
  26  of emails has been sent. You could manage this manually within a loop, but the
  27  AntiFlood plugin provides the necessary wrapper code so that you don't need to
  28  worry about this logic.
  29  
  30  Regardless of limits imposed by the server, it's usually a good idea to be
  31  conservative with the resources of the SMTP server. Sending will become
  32  sluggish if the server is being over-used so using the AntiFlood plugin will
  33  not be a bad idea even if no limits exist.
  34  
  35  The AntiFlood plugin's logic is basically to disconnect and the immediately
  36  re-connect with the SMTP server every X number of emails sent, where X is a
  37  number you specify to the plugin.
  38  
  39  You can also specify a time period in seconds that Swift Mailer should pause
  40  for between the disconnect/re-connect process. It's a good idea to pause for a
  41  short time (say 30 seconds every 100 emails) simply to give the SMTP server a
  42  chance to process its queue and recover some resources.
  43  
  44  Using the AntiFlood Plugin
  45  ~~~~~~~~~~~~~~~~~~~~~~~~~~
  46  
  47  The AntiFlood Plugin -- like all plugins -- is added with the Mailer class's
  48  ``registerPlugin()`` method. It takes two constructor parameters: the number of
  49  emails to pause after, and optionally the number of seconds to pause for.
  50  
  51  When Swift Mailer sends messages it will count the number of messages that have
  52  been sent since the last re-connect. Once the number hits your specified
  53  threshold it will disconnect and re-connect, optionally pausing for a specified
  54  amount of time::
  55  
  56      // Create the Mailer using any Transport
  57      $mailer = new Swift_Mailer(
  58        new Swift_SmtpTransport('smtp.example.org', 25)
  59      );
  60  
  61      // Use AntiFlood to re-connect after 100 emails
  62      $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100));
  63  
  64      // And specify a time in seconds to pause for (30 secs)
  65      $mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
  66  
  67      // Continue sending as normal
  68      for ($lotsOfRecipients as $recipient) {
  69        ...
  70  
  71        $mailer->send( ... );
  72      }
  73  
  74  Throttler Plugin
  75  ----------------
  76  
  77  If your SMTP server has restrictions in place to limit the rate at which you
  78  send emails, then your code will need to be aware of this rate-limiting. The
  79  Throttler plugin makes Swift Mailer run at a rate-limited speed.
  80  
  81  Many shared hosts don't open their SMTP servers as a free-for-all. Usually they
  82  have policies in place (probably to discourage spammers) that only allow you to
  83  send a fixed number of emails per-hour/day.
  84  
  85  The Throttler plugin supports two modes of rate-limiting and with each, you
  86  will need to do that math to figure out the values you want. The plugin can
  87  limit based on the number of emails per minute, or the number of
  88  bytes-transferred per-minute.
  89  
  90  Using the Throttler Plugin
  91  ~~~~~~~~~~~~~~~~~~~~~~~~~~
  92  
  93  The Throttler Plugin -- like all plugins -- is added with the Mailer class'
  94  ``registerPlugin()`` method. It has two required constructor parameters that
  95  tell it how to do its rate-limiting.
  96  
  97  When Swift Mailer sends messages it will keep track of the rate at which
  98  sending messages is occurring. If it realises that sending is happening too
  99  fast, it will cause your program to ``sleep()`` for enough time to average out
 100  the rate::
 101  
 102      // Create the Mailer using any Transport
 103      $mailer = new Swift_Mailer(
 104        new Swift_SmtpTransport('smtp.example.org', 25)
 105      );
 106  
 107      // Rate limit to 100 emails per-minute
 108      $mailer->registerPlugin(new Swift_Plugins_ThrottlerPlugin(
 109        100, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE
 110      ));
 111  
 112      // Rate limit to 10MB per-minute
 113      $mailer->registerPlugin(new Swift_Plugins_ThrottlerPlugin(
 114        1024 * 1024 * 10, Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE
 115      ));
 116  
 117      // Continue sending as normal
 118      for ($lotsOfRecipients as $recipient) {
 119        ...
 120  
 121        $mailer->send( ... );
 122      }
 123  
 124  Logger Plugin
 125  -------------
 126  
 127  The Logger plugins helps with debugging during the process of sending. It can
 128  help to identify why an SMTP server is rejecting addresses, or any other
 129  hard-to-find problems that may arise.
 130  
 131  The Logger plugin comes in two parts. There's the plugin itself, along with one
 132  of a number of possible Loggers that you may choose to use. For example, the
 133  logger may output messages directly in realtime, or it may capture messages in
 134  an array.
 135  
 136  One other notable feature is the way in which the Logger plugin changes
 137  Exception messages. If Exceptions are being thrown but the error message does
 138  not provide conclusive information as to the source of the problem (such as an
 139  ambiguous SMTP error) the Logger plugin includes the entire SMTP transcript in
 140  the error message so that debugging becomes a simpler task.
 141  
 142  There are a few available Loggers included with Swift Mailer, but writing your
 143  own implementation is incredibly simple and is achieved by creating a short
 144  class that implements the ``Swift_Plugins_Logger`` interface.
 145  
 146  * ``Swift_Plugins_Loggers_ArrayLogger``: Keeps a collection of log messages
 147    inside an array. The array content can be cleared or dumped out to the screen.
 148  
 149  * ``Swift_Plugins_Loggers_EchoLogger``: Prints output to the screen in
 150    realtime. Handy for very rudimentary debug output.
 151  
 152  Using the Logger Plugin
 153  ~~~~~~~~~~~~~~~~~~~~~~~
 154  
 155  The Logger Plugin -- like all plugins -- is added with the Mailer class'
 156  ``registerPlugin()`` method. It accepts an instance of ``Swift_Plugins_Logger``
 157  in its constructor.
 158  
 159  When Swift Mailer sends messages it will keep a log of all the interactions
 160  with the underlying Transport being used. Depending upon the Logger that has
 161  been used the behaviour will differ, but all implementations offer a way to get
 162  the contents of the log::
 163  
 164      // Create the Mailer using any Transport
 165      $mailer = new Swift_Mailer(
 166       new Swift_SmtpTransport('smtp.example.org', 25)
 167      );
 168  
 169      // To use the ArrayLogger
 170      $logger = new Swift_Plugins_Loggers_ArrayLogger();
 171      $mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));
 172  
 173      // Or to use the Echo Logger
 174      $logger = new Swift_Plugins_Loggers_EchoLogger();
 175      $mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($logger));
 176  
 177      // Continue sending as normal
 178      for ($lotsOfRecipients as $recipient) {
 179       ...
 180  
 181       $mailer->send( ... );
 182      }
 183  
 184      // Dump the log contents
 185      // NOTE: The EchoLogger dumps in realtime so dump() does nothing for it
 186      echo $logger->dump();
 187  
 188  Decorator Plugin
 189  ----------------
 190  
 191  Often there's a need to send the same message to multiple recipients, but with
 192  tiny variations such as the recipient's name being used inside the message
 193  body. The Decorator plugin aims to provide a solution for allowing these small
 194  differences.
 195  
 196  The decorator plugin works by intercepting the sending process of Swift Mailer,
 197  reading the email address in the To: field and then looking up a set of
 198  replacements for a template.
 199  
 200  While the use of this plugin is simple, it is probably the most commonly
 201  misunderstood plugin due to the way in which it works. The typical mistake
 202  users make is to try registering the plugin multiple times (once for each
 203  recipient) -- inside a loop for example. This is incorrect.
 204  
 205  The Decorator plugin should be registered just once, but containing the list of
 206  all recipients prior to sending. It will use this list of recipients to find
 207  the required replacements during sending.
 208  
 209  Using the Decorator Plugin
 210  ~~~~~~~~~~~~~~~~~~~~~~~~~~
 211  
 212  To use the Decorator plugin, simply create an associative array of replacements
 213  based on email addresses and then use the mailer's ``registerPlugin()`` method
 214  to add the plugin.
 215  
 216  First create an associative array of replacements based on the email addresses
 217  you'll be sending the message to.
 218  
 219  .. note::
 220  
 221      The replacements array becomes a 2-dimensional array whose keys are the
 222      email addresses and whose values are an associative array of replacements
 223      for that email address. The curly braces used in this example can be any
 224      type of syntax you choose, provided they match the placeholders in your
 225      email template::
 226  
 227          $replacements = [];
 228          foreach ($users as $user) {
 229            $replacements[$user['email']] = [
 230              '{username}'=>$user['username'],
 231              '{resetcode}'=>$user['resetcode']
 232            ];
 233          }
 234  
 235  Now create an instance of the Decorator plugin using this array of replacements
 236  and then register it with the Mailer. Do this only once!
 237  
 238  ::
 239  
 240      $decorator = new Swift_Plugins_DecoratorPlugin($replacements);
 241  
 242      $mailer->registerPlugin($decorator);
 243  
 244  When you create your message, replace elements in the body (and/or the subject
 245  line) with your placeholders::
 246  
 247      $message = (new Swift_Message())
 248        ->setSubject('Important notice for {username}')
 249        ->setBody(
 250          "Hello {username}, you requested to reset your password.\n" .
 251          "Please visit https://example.com/pwreset and use the reset code {resetcode} to set a new password."
 252        )
 253        ;
 254  
 255      foreach ($users as $user) {
 256        $message->addTo($user['email']);
 257      }
 258  
 259  When you send this message to each of your recipients listed in your
 260  ``$replacements`` array they will receive a message customized for just
 261  themselves. For example, the message used above when received may appear like
 262  this to one user:
 263  
 264  .. code-block:: text
 265  
 266      Subject: Important notice for smilingsunshine2009
 267  
 268      Hello smilingsunshine2009,you requested to reset your password.
 269      Please visit https://example.com/pwreset and use the reset code 183457 to set a new password.
 270  
 271  While another use may receive the message as:
 272  
 273  .. code-block:: text
 274  
 275      Subject: Important notice for billy-bo-bob
 276  
 277      Hello billy-bo-bob, you requested to reset your password.
 278      Please visit https://example.com/pwreset and use the reset code 539127 to set a new password.
 279  
 280  While the decorator plugin provides a means to solve this problem, there are
 281  various ways you could tackle this problem without the need for a plugin. We're
 282  trying to come up with a better way ourselves and while we have several
 283  (obvious) ideas we don't quite have the perfect solution to go ahead and
 284  implement it. Watch this space.
 285  
 286  Providing Your Own Replacements Lookup for the Decorator
 287  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 288  
 289  Filling an array with replacements may not be the best solution for providing
 290  replacement information to the decorator. If you have a more elegant algorithm
 291  that performs replacement lookups on-the-fly you may provide your own
 292  implementation.
 293  
 294  Providing your own replacements lookup implementation for the Decorator is
 295  simply a matter of passing an instance of
 296  ``Swift_Plugins_Decorator_Replacements`` to the decorator plugin's constructor,
 297  rather than passing in an array.
 298  
 299  The Replacements interface is very simple to implement since it has just one
 300  method: ``getReplacementsFor($address)``.
 301  
 302  Imagine you want to look up replacements from a database on-the-fly, you might
 303  provide an implementation that does this. You need to create a small class::
 304  
 305      class DbReplacements implements Swift_Plugins_Decorator_Replacements {
 306        public function getReplacementsFor($address) {
 307          global $db; // Your PDO instance with a connection to your database
 308          $query = $db->prepare(
 309            "SELECT * FROM `users` WHERE `email` = ?"
 310          );
 311  
 312          $query->execute([$address]);
 313  
 314          if ($row = $query->fetch(PDO::FETCH_ASSOC)) {
 315            return [
 316              '{username}'=>$row['username'],
 317              '{resetcode}'=>$row['resetcode']
 318            ];
 319          }
 320        }
 321      }
 322  
 323  Now all you need to do is pass an instance of your class into the Decorator
 324  plugin's constructor instead of passing an array::
 325  
 326      $decorator = new Swift_Plugins_DecoratorPlugin(new DbReplacements());
 327  
 328      $mailer->registerPlugin($decorator);
 329  
 330  For each message sent, the plugin will call your class'
 331  ``getReplacementsFor()`` method to find the array of replacements it needs.
 332  
 333  .. note::
 334  
 335      If your lookup algorithm is case sensitive, you should transform the
 336      ``$address`` argument as appropriate -- for example by passing it through
 337      ``strtolower()``.


Generated: Tue May 19 15:55:14 2020 Cross-referenced by PHPXref 0.7.1