Overview
Sending mails is a web developer's everyday task, and symfony 1.2 lets you do this easier than ever using Swift Mailer.
Swift Mailer is a well thought out, fully featured PHP5 object library that should cover all of your mailing needs.
caution
SwiftMailer is now up to version 4.x which is not available via svn. Check http://swiftmailer.org for details, and make the necessary adjustments below (pending documentation update).
It is available in a tagged SVN repository, so your project won't break just because the library is updated. It will be up to you to switch to a newer version.
Symfony's way to send emails from a project is very simple. You create a partial or a component that will render the e-mail content, and use Swift to send it in a flexible way.
Installing
If your project is already using svn, you can install it using the svn:externals
property:
$ cd /path/to/symfony/project $ mkdir -p lib/vendor $ cd lib/vendor $ svn propedit svn:externals .
Then add the following line:
swift http://swiftmailer.svn.sourceforge.net/svnroot/swiftmailer/tags/php5/3.3.3/lib/
And run:
$ svn update
If your project is not using SVN, you can still get this part as a subversion working copy by checking out the tag.
$ cd /path/to/symfony/project $ mkdir -p lib/vendor $ cd lib/vendor $ svn checkout http://swiftmailer.svn.sourceforge.net/svnroot/swiftmailer/tags/php5/3.3.3/lib/ swift
Just clear your cache to force class autoloading resolution to be flushed, and you're done with the installation.
Configuration
There is no mailer-specific configuration.
To keep your project flexible, you should use app.yml
configuration file to keep hard-written e-mail addresses. This way, you can have different senders/receivers addresses depending on the environment you're on, and when one will need to change it, he won't have to dig all the project code. The place to change it will be just too obvious.
Render an e-mail
As of symfony 1.1 RC2, you can easily get rendered partials and components from an action:
$mailBody = $this->getPartial('mailBody', array('name' => 'John Doe'));
or
$mailBody = $this->getComponent('mail', 'mailBody', array('name' => 'John Doe'));
Send an HTML e-mail
Then we send the mail rendered above using Swift:
try { // Create the mailer and message objects $mailer = new Swift(new Swift_Connection_NativeMail()); $message = new Swift_Message('Mail\'s subject', $mailBody, 'text/html'); // Send $mailer->send($message, $mailTo, $mailFrom); $mailer->disconnect(); } catch (Exception $e) { $mailer->disconnect(); // handle errors here }
Send a multipart e-mail
Some e-mail clients don't like HTML at all, so it's usually a good idea to provide your mail in both html and plain text.
try { // Create the mailer and message objects $mailer = new Swift(new Swift_Connection_NativeMail()); $message = new Swift_Message('Test mail subject'); // Render message parts $mailContext = array('name' => 'John Doe'); $message->attach(new Swift_Message_Part($this->getPartial('mail/mailHtmlBody', $mailContext), 'text/html')); $message->attach(new Swift_Message_Part($this->getPartial('mail/mailTextBody', $mailContext), 'text/plain')); // Send $mailer->send($message, $mailTo, $mailFrom); $mailer->disconnect(); } catch (Exception $e) { $mailer->disconnect(); // handle errors there }
Use different connection settings
When you create the Swift object, you can use a different Swift_Connection object.
Swift_Connection_NativeMail is the connection driver using the native PHP
mail()
function.Swift_Connection_SMTP sends mail via a SMTP server. The constructor takes three parameters, all of which are optional:
public function __construct($server="localhost", $port=null, $encryption=null)
We'll see in a few how to use this to send a mail via a secure mail server, using gMail secure SMTP in occurence.
Swift_Connection_Sendmail uses a sendmail binary to send the mail. You can specify its path to the constructor.
Swift_Connection_Multi is the first special driver, that can be used to combine more than one connection driver. It provides redundancy in the event that a SMTP server is unavailable at the time of the request. The constructor takes an array of
Swift_Connection
object instances, and can even embed otherSwift_Connection_Multi
instances (even if the advantage of doing so might be a bit obscure)Swift_Connection_Rotator is the last one, doing a bit more than
Swift_Connection_Multi
by keeping track of down servers, and managing rotation of "alive" servers. How to use it is beyond the scope of this cookbook recipe, and you should refer to the Swift Mailer documentation.
Using Google Mail SMTP servers
Why would you like to use a gmail account to send your emails?
- You don't have to setup and maintain a SMTP server
- You won't be marked as spam for hotmail users (or similar)
- You get a carbon copy in your gmail account's
Sent Mails
, allowing easy debug
What are the limitations?
- You need a gmail account
- SMTP over SSL negociation is longer than plain SMTP negociation
- You cannot send an e-mail from an arbitrary email address (but you can add a new send-mail-as address in gmail settings/account)
Here is how to configure the Swift object:
$connection = new Swift_Connection_SMTP('smtp.gmail.com', 465, Swift_Connection_SMTP::ENC_SSL); $connection->setUsername('romain@gmail.com'); $connection->setPassword('SuperSecurePassword'); $mailer = new Swift($connection);
Embed images
To embed images in your mail, you need to get mail-dependant URLs from the embedded objects before rendering its content. Here's an example how you can do it.
// Create the mailer and message objects $mailer = new Swift(new Swift_Connection_NativeMail()); $message = new Swift_Message('Test mail subject'); // Inline images $images = array(); $images['symfony'] = new Swift_Message_Image(new Swift_File(sfConfig::get('sf_web_dir').'/legacy/images/symfony.gif')); $images['swift'] = new Swift_Message_Image(new Swift_File(sfConfig::get('sf_web_dir').'/legacy/images/swift.jpg')); $imageReferences = array(); foreach ($images as $name => $image) { $imageReferences[$name] = $message->attach($image); } // Render message parts $mailContext = array('name' => 'John Doe', 'images' => $imageReferences); $message->attach(new Swift_Message_Part($this->getPartial('mail/mailHtmlBody', $mailContext), 'text/html')); $message->attach(new Swift_Message_Part($this->getPartial('mail/mailTextBody', $mailContext), 'text/plain')); // Send $mailer->send($message, $mailTo, $mailFrom); $mailer->disconnect();
Now in your component/partial template you can easily display those attached pictures like this:
<img src="<?php echo $images['symfony']; ?>" alt="Symfony Project" /> <img src="<?php echo $images['swift']; ?>" alt="Swift Mailer" />
Wasn't that easy?
Attachments
Attaching a document to a mail is as simple as you would expect it to be:
$message->attach(new Swift_Message_Attachment(new Swift_File($file), $filename, $mime_type));
Recipient lists
You'll often want to have more than one recipient or carbon copies for a mail. This is done using the Swift_RecipientList
class.
$recipients = new Swift_RecipientList(); $recipients->addTo($to); $recipients->addCc($cc); $recipients->addBcc($bcc);
If you're sending e-mails in a loop, don't forget to ->flush()
your $recipients list, or you'll have a bad time explaining why someone received 500 copies of the same mailing list.
Sending emails from a task
The process is exactly the same as doing it from an action, with one little
difference: You cannot use sfAction
methods anymore.
You'll need to use get_partial()
and get_component()
functions in
PartialHelper
instead of sfAction::getPartial()
and
sfAction::getComponent()
methods.
tip
To load a helper from anywere in your application, you can use the following:
sfProjectConfiguration::getActive()->loadHelpers("Partial", "Url", "MyHelper");
Getting documented
The SwiftMailer website is a gold mine of documentation and tutorials.
This work is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.