PageRenderTime 51ms CodeModel.GetById 43ms app.highlight 6ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/swiftmailer/swiftmailer/doc/plugins.rst

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