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