You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

572 lines
20KB

  1. Sending Messages
  2. ================
  3. Quick Reference for Sending a Message
  4. -------------------------------------
  5. Sending a message is very straightforward. You create a Transport, use it to
  6. create the Mailer, then you use the Mailer to send the message.
  7. To send a Message:
  8. * Create a Transport from one of the provided Transports --
  9. ``Swift_SmtpTransport``, ``Swift_SendmailTransport``
  10. or one of the aggregate Transports.
  11. * Create an instance of the ``Swift_Mailer`` class, using the Transport as
  12. it's constructor parameter.
  13. * Create a Message.
  14. * Send the message via the ``send()`` method on the Mailer object.
  15. .. caution::
  16. The ``Swift_SmtpTransport`` and ``Swift_SendmailTransport`` transports use
  17. ``proc_*`` PHP functions, which might not be available on your PHP
  18. installation. You can easily check if that's the case by running the
  19. following PHP script: ``<?php echo function_exists('proc_open') ? "Yep,
  20. that will work" : "Sorry, that won't work";``
  21. When using ``send()`` the message will be sent just like it would be sent if you
  22. used your mail client. An integer is returned which includes the number of
  23. successful recipients. If none of the recipients could be sent to then zero will
  24. be returned, which equates to a boolean ``false``. If you set two ``To:``
  25. recipients and three ``Bcc:`` recipients in the message and all of the
  26. recipients are delivered to successfully then the value 5 will be returned.
  27. .. code-block:: php
  28. require_once 'lib/swift_required.php';
  29. // Create the Transport
  30. $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25)
  31. ->setUsername('your username')
  32. ->setPassword('your password')
  33. ;
  34. /*
  35. You could alternatively use a different transport such as Sendmail:
  36. // Sendmail
  37. $transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
  38. */
  39. // Create the Mailer using your created Transport
  40. $mailer = Swift_Mailer::newInstance($transport);
  41. // Create a message
  42. $message = Swift_Message::newInstance('Wonderful Subject')
  43. ->setFrom(array('john@doe.com' => 'John Doe'))
  44. ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
  45. ->setBody('Here is the message itself')
  46. ;
  47. // Send the message
  48. $result = $mailer->send($message);
  49. Transport Types
  50. ~~~~~~~~~~~~~~~
  51. A Transport is the component which actually does the sending. You need to
  52. provide a Transport object to the Mailer class and there are several possible
  53. options.
  54. Typically you will not need to know how a Transport works under-the-surface,
  55. you will only need to know how to create an instance of one, and which one to
  56. use for your environment.
  57. The SMTP Transport
  58. ..................
  59. The SMTP Transport sends messages over the (standardized) Simple Message
  60. Transfer Protocol. It can deal with encryption and authentication.
  61. The SMTP Transport, ``Swift_SmtpTransport`` is without doubt the most commonly
  62. used Transport because it will work on 99% of web servers (I just made that
  63. number up, but you get the idea). All the server needs is the ability to
  64. connect to a remote (or even local) SMTP server on the correct port number
  65. (usually 25).
  66. SMTP servers often require users to authenticate with a username and password
  67. before any mail can be sent to other domains. This is easily achieved using
  68. Swift Mailer with the SMTP Transport.
  69. SMTP is a protocol -- in other words it's a "way" of communicating a job
  70. to be done (i.e. sending a message). The SMTP protocol is the fundamental
  71. basis on which messages are delivered all over the internet 7 days a week, 365
  72. days a year. For this reason it's the most "direct" method of sending messages
  73. you can use and it's the one that will give you the most power and feedback
  74. (such as delivery failures) when using Swift Mailer.
  75. Because SMTP is generally run as a remote service (i.e. you connect to it over
  76. the network/internet) it's extremely portable from server-to-server. You can
  77. easily store the SMTP server address and port number in a configuration file
  78. within your application and adjust the settings accordingly if the code is
  79. moved or if the SMTP server is changed.
  80. Some SMTP servers -- Google for example -- use encryption for security reasons.
  81. Swift Mailer supports using both SSL and TLS encryption settings.
  82. Using the SMTP Transport
  83. ^^^^^^^^^^^^^^^^^^^^^^^^
  84. The SMTP Transport is easy to use. Most configuration options can be set with
  85. the constructor.
  86. To use the SMTP Transport you need to know which SMTP server your code needs
  87. to connect to. Ask your web host if you're not sure. Lots of people ask me who
  88. to connect to -- I really can't answer that since it's a setting that's
  89. extremely specific to your hosting environment.
  90. To use the SMTP Transport:
  91. * Call ``Swift_SmtpTransport::newInstance()`` with the SMTP server name and
  92. optionally with a port number (defaults to 25).
  93. * Use the returned object to create the Mailer.
  94. A connection to the SMTP server will be established upon the first call to
  95. ``send()``.
  96. .. code-block:: php
  97. require_once 'lib/swift_required.php';
  98. // Create the Transport
  99. $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25);
  100. // Create the Mailer using your created Transport
  101. $mailer = Swift_Mailer::newInstance($transport);
  102. /*
  103. It's also possible to use multiple method calls
  104. $transport = Swift_SmtpTransport::newInstance()
  105. ->setHost('smtp.example.org')
  106. ->setPort(25)
  107. ;
  108. */
  109. Encrypted SMTP
  110. ^^^^^^^^^^^^^^
  111. You can use SSL or TLS encryption with the SMTP Transport by specifying it as
  112. a parameter or with a method call.
  113. To use encryption with the SMTP Transport:
  114. * Pass the encryption setting as a third parameter to
  115. ``Swift_SmtpTransport::newInstance()``; or
  116. * Call the ``setEncryption()`` method on the Transport.
  117. A connection to the SMTP server will be established upon the first call to
  118. ``send()``. The connection will be initiated with the correct encryption
  119. settings.
  120. .. note::
  121. For SSL or TLS encryption to work your PHP installation must have
  122. appropriate OpenSSL transports wrappers. You can check if "tls" and/or
  123. "ssl" are present in your PHP installation by using the PHP function
  124. ``stream_get_transports()``
  125. .. code-block:: php
  126. require_once 'lib/swift_required.php';
  127. // Create the Transport
  128. $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 587, 'ssl');
  129. // Create the Mailer using your created Transport
  130. $mailer = Swift_Mailer::newInstance($transport);
  131. /*
  132. It's also possible to use multiple method calls
  133. $transport = Swift_SmtpTransport::newInstance()
  134. ->setHost('smtp.example.org')
  135. ->setPort(587)
  136. ->setEncryption('ssl')
  137. ;
  138. */
  139. SMTP with a Username and Password
  140. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  141. Some servers require authentication. You can provide a username and password
  142. with ``setUsername()`` and ``setPassword()`` methods.
  143. To use a username and password with the SMTP Transport:
  144. * Create the Transport with ``Swift_SmtpTransport::newInstance()``.
  145. * Call the ``setUsername()`` and ``setPassword()`` methods on the Transport.
  146. Your username and password will be used to authenticate upon first connect
  147. when ``send()`` are first used on the Mailer.
  148. If authentication fails, an Exception of type ``Swift_TransportException`` will
  149. be thrown.
  150. .. note::
  151. If you need to know early whether or not authentication has failed and an
  152. Exception is going to be thrown, call the ``start()`` method on the
  153. created Transport.
  154. .. code-block:: php
  155. require_once 'lib/swift_required.php';
  156. // Create the Transport the call setUsername() and setPassword()
  157. $transport = Swift_SmtpTransport::newInstance('smtp.example.org', 25)
  158. ->setUsername('username')
  159. ->setPassword('password')
  160. ;
  161. // Create the Mailer using your created Transport
  162. $mailer = Swift_Mailer::newInstance($transport);
  163. The Sendmail Transport
  164. ......................
  165. The Sendmail Transport sends messages by communicating with a locally
  166. installed MTA -- such as ``sendmail``.
  167. The Sendmail Transport, ``Swift_SendmailTransport`` does not directly connect to
  168. any remote services. It is designed for Linux servers that have ``sendmail``
  169. installed. The Transport starts a local ``sendmail`` process and sends messages
  170. to it. Usually the ``sendmail`` process will respond quickly as it spools your
  171. messages to disk before sending them.
  172. The Transport is named the Sendmail Transport for historical reasons
  173. (``sendmail`` was the "standard" UNIX tool for sending e-mail for years). It
  174. will send messages using other transfer agents such as Exim or Postfix despite
  175. its name, provided they have the relevant sendmail wrappers so that they can be
  176. started with the correct command-line flags.
  177. It's a common misconception that because the Sendmail Transport returns a
  178. result very quickly it must therefore deliver messages to recipients quickly
  179. -- this is not true. It's not slow by any means, but it's certainly not
  180. faster than SMTP when it comes to getting messages to the intended recipients.
  181. This is because sendmail itself sends the messages over SMTP once they have
  182. been quickly spooled to disk.
  183. The Sendmail Transport has the potential to be just as smart of the SMTP
  184. Transport when it comes to notifying Swift Mailer about which recipients were
  185. rejected, but in reality the majority of locally installed ``sendmail``
  186. instances are not configured well enough to provide any useful feedback. As such
  187. Swift Mailer may report successful deliveries where they did in fact fail before
  188. they even left your server.
  189. You can run the Sendmail Transport in two different modes specified by command
  190. line flags:
  191. * "``-bs``" runs in SMTP mode so theoretically it will act like the SMTP
  192. Transport
  193. * "``-t``" runs in piped mode with no feedback, but theoretically faster,
  194. though not advised
  195. You can think of the Sendmail Transport as a sort of asynchronous SMTP Transport
  196. -- though if you have problems with delivery failures you should try using the
  197. SMTP Transport instead. Swift Mailer isn't doing the work here, it's simply
  198. passing the work to somebody else (i.e. ``sendmail``).
  199. Using the Sendmail Transport
  200. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  201. To use the Sendmail Transport you simply need to call
  202. ``Swift_SendmailTransport::newInstance()`` with the command as a parameter.
  203. To use the Sendmail Transport you need to know where ``sendmail`` or another MTA
  204. exists on the server. Swift Mailer uses a default value of
  205. ``/usr/sbin/sendmail``, which should work on most systems.
  206. You specify the entire command as a parameter (i.e. including the command line
  207. flags). Swift Mailer supports operational modes of "``-bs``" (default) and
  208. "``-t``".
  209. .. note::
  210. If you run sendmail in "``-t``" mode you will get no feedback as to whether
  211. or not sending has succeeded. Use "``-bs``" unless you have a reason not to.
  212. To use the Sendmail Transport:
  213. * Call ``Swift_SendmailTransport::newInstance()`` with the command, including
  214. the correct command line flags. The default is to use ``/usr/sbin/sendmail
  215. -bs`` if this is not specified.
  216. * Use the returned object to create the Mailer.
  217. A sendmail process will be started upon the first call to ``send()``. If the
  218. process cannot be started successfully an Exception of type
  219. ``Swift_TransportException`` will be thrown.
  220. .. code-block:: php
  221. require_once 'lib/swift_required.php';
  222. // Create the Transport
  223. $transport = Swift_SendmailTransport::newInstance('/usr/sbin/exim -bs');
  224. // Create the Mailer using your created Transport
  225. $mailer = Swift_Mailer::newInstance($transport);
  226. The Mail Transport
  227. ..................
  228. The Mail Transport sends messages by delegating to PHP's internal
  229. ``mail()`` function.
  230. In my experience -- and others' -- the ``mail()`` function is not particularly
  231. predictable, or helpful.
  232. Quite notably, the ``mail()`` function behaves entirely differently between
  233. Linux and Windows servers. On linux it uses ``sendmail``, but on Windows it uses
  234. SMTP.
  235. In order for the ``mail()`` function to even work at all ``php.ini`` needs to be
  236. configured correctly, specifying the location of sendmail or of an SMTP server.
  237. The problem with ``mail()`` is that it "tries" to simplify things to the point
  238. that it actually makes things more complex due to poor interface design. The
  239. developers of Swift Mailer have gone to a lot of effort to make the Mail
  240. Transport work with a reasonable degree of consistency.
  241. Serious drawbacks when using this Transport are:
  242. * Unpredictable message headers
  243. * Lack of feedback regarding delivery failures
  244. * Lack of support for several plugins that require real-time delivery feedback
  245. It's a last resort, and we say that with a passion!
  246. Available Methods for Sending Messages
  247. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  248. The Mailer class offers two methods for sending Messages -- ``send()``.
  249. Each behaves in a slightly different way.
  250. When a message is sent in Swift Mailer, the Mailer class communicates with
  251. whichever Transport class you have chosen to use.
  252. Each recipient in the message should either be accepted or rejected by the
  253. Transport. For example, if the domain name on the email address is not
  254. reachable the SMTP Transport may reject the address because it cannot process
  255. it. Whichever method you use -- ``send()`` -- Swift Mailer will return
  256. an integer indicating the number of accepted recipients.
  257. .. note::
  258. It's possible to find out which recipients were rejected -- we'll cover that
  259. later in this chapter.
  260. Using the ``send()`` Method
  261. ...........................
  262. The ``send()`` method of the ``Swift_Mailer`` class sends a message using
  263. exactly the same logic as your Desktop mail client would use. Just pass it a
  264. Message and get a result.
  265. To send a Message with ``send()``:
  266. * Create a Transport from one of the provided Transports --
  267. ``Swift_SmtpTransport``, ``Swift_SendmailTransport``,
  268. or one of the aggregate Transports.
  269. * Create an instance of the ``Swift_Mailer`` class, using the Transport as
  270. it's constructor parameter.
  271. * Create a Message.
  272. * Send the message via the ``send()`` method on the Mailer object.
  273. The message will be sent just like it would be sent if you used your mail
  274. client. An integer is returned which includes the number of successful
  275. recipients. If none of the recipients could be sent to then zero will be
  276. returned, which equates to a boolean ``false``. If you set two
  277. ``To:`` recipients and three ``Bcc:`` recipients in the message and all of the
  278. recipients are delivered to successfully then the value 5 will be returned.
  279. .. code-block:: php
  280. require_once 'lib/swift_required.php';
  281. // Create the Transport
  282. $transport = Swift_SmtpTransport::newInstance('localhost', 25);
  283. // Create the Mailer using your created Transport
  284. $mailer = Swift_Mailer::newInstance($transport);
  285. // Create a message
  286. $message = Swift_Message::newInstance('Wonderful Subject')
  287. ->setFrom(array('john@doe.com' => 'John Doe'))
  288. ->setTo(array('receiver@domain.org', 'other@domain.org' => 'A name'))
  289. ->setBody('Here is the message itself')
  290. ;
  291. // Send the message
  292. $numSent = $mailer->send($message);
  293. printf("Sent %d messages\n", $numSent);
  294. /* Note that often that only the boolean equivalent of the
  295. return value is of concern (zero indicates FALSE)
  296. if ($mailer->send($message))
  297. {
  298. echo "Sent\n";
  299. }
  300. else
  301. {
  302. echo "Failed\n";
  303. }
  304. */
  305. Sending Emails in Batch
  306. .......................
  307. If you want to send a separate message to each recipient so that only their
  308. own address shows up in the ``To:`` field, follow the following recipe:
  309. * Create a Transport from one of the provided Transports --
  310. ``Swift_SmtpTransport``, ``Swift_SendmailTransport``,
  311. or one of the aggregate Transports.
  312. * Create an instance of the ``Swift_Mailer`` class, using the Transport as
  313. it's constructor parameter.
  314. * Create a Message.
  315. * Iterate over the recipients and send message via the ``send()`` method on
  316. the Mailer object.
  317. Each recipient of the messages receives a different copy with only their own
  318. email address on the ``To:`` field.
  319. Make sure to add only valid email addresses as recipients. If you try to add an
  320. invalid email address with ``setTo()``, ``setCc()`` or ``setBcc()``, Swift
  321. Mailer will throw a ``Swift_RfcComplianceException``.
  322. If you add recipients automatically based on a data source that may contain
  323. invalid email addresses, you can prevent possible exceptions by validating the
  324. addresses using ``Swift_Validate::email($email)`` and only adding addresses
  325. that validate. Another way would be to wrap your ``setTo()``, ``setCc()`` and
  326. ``setBcc()`` calls in a try-catch block and handle the
  327. ``Swift_RfcComplianceException`` in the catch block.
  328. Handling invalid addresses properly is especially important when sending emails
  329. in large batches since a single invalid address might cause an unhandled
  330. exception and stop the execution or your script early.
  331. .. note::
  332. In the following example, two emails are sent. One to each of
  333. ``receiver@domain.org`` and ``other@domain.org``. These recipients will
  334. not be aware of each other.
  335. .. code-block:: php
  336. require_once 'lib/swift_required.php';
  337. // Create the Transport
  338. $transport = Swift_SmtpTransport::newInstance('localhost', 25);
  339. // Create the Mailer using your created Transport
  340. $mailer = Swift_Mailer::newInstance($transport);
  341. // Create a message
  342. $message = Swift_Message::newInstance('Wonderful Subject')
  343. ->setFrom(array('john@doe.com' => 'John Doe'))
  344. ->setBody('Here is the message itself')
  345. ;
  346. // Send the message
  347. $failedRecipients = array();
  348. $numSent = 0;
  349. $to = array('receiver@domain.org', 'other@domain.org' => 'A name');
  350. foreach ($to as $address => $name)
  351. {
  352. if (is_int($address)) {
  353. $message->setTo($name);
  354. } else {
  355. $message->setTo(array($address => $name));
  356. }
  357. $numSent += $mailer->send($message, $failedRecipients);
  358. }
  359. printf("Sent %d messages\n", $numSent);
  360. Finding out Rejected Addresses
  361. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  362. It's possible to get a list of addresses that were rejected by the Transport
  363. by using a by-reference parameter to ``send()``.
  364. As Swift Mailer attempts to send the message to each address given to it, if a
  365. recipient is rejected it will be added to the array. You can pass an existing
  366. array, otherwise one will be created by-reference.
  367. Collecting the list of recipients that were rejected can be useful in
  368. circumstances where you need to "prune" a mailing list for example when some
  369. addresses cannot be delivered to.
  370. Getting Failures By-reference
  371. .............................
  372. Collecting delivery failures by-reference with the ``send()`` method is as
  373. simple as passing a variable name to the method call.
  374. To get failed recipients by-reference:
  375. * Pass a by-reference variable name to the ``send()`` method of the Mailer
  376. class.
  377. If the Transport rejects any of the recipients, the culprit addresses will be
  378. added to the array provided by-reference.
  379. .. note::
  380. If the variable name does not yet exist, it will be initialized as an
  381. empty array and then failures will be added to that array. If the variable
  382. already exists it will be type-cast to an array and failures will be added
  383. to it.
  384. .. code-block:: php
  385. $mailer = Swift_Mailer::newInstance( ... );
  386. $message = Swift_Message::newInstance( ... )
  387. ->setFrom( ... )
  388. ->setTo(array(
  389. 'receiver@bad-domain.org' => 'Receiver Name',
  390. 'other@domain.org' => 'A name',
  391. 'other-receiver@bad-domain.org' => 'Other Name'
  392. ))
  393. ->setBody( ... )
  394. ;
  395. // Pass a variable name to the send() method
  396. if (!$mailer->send($message, $failures))
  397. {
  398. echo "Failures:";
  399. print_r($failures);
  400. }
  401. /*
  402. Failures:
  403. Array (
  404. 0 => receiver@bad-domain.org,
  405. 1 => other-receiver@bad-domain.org
  406. )
  407. */