![]() |
|
The symfony CookbookHow to send an email |
|

You are currently reading "The symfony Cookbook" which is licensed under the Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License license.
|
This work is licensed under a
Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.
Translation of this work into another language is explicitly allowed. |
Sending mails is a web developer's everyday task, and symfony 1.1 let you do this easier than ever using Swift Mailer.
Swift Mailer is a well thought, fully featured PHP5 object library that will cover 120% of your mailing needs.
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.
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.
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.
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'));
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 }
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 }
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 other Swift_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.
Why would you like to use a gmail account to send your emails?
Sent Mails, allowing easy debugWhat are the limitations?
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);
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').'/images/symfony.gif')); $images['swift'] = new Swift_Message_Image(new Swift_File(sfConfig::get('sf_web_dir').'/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?
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));
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.
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.
The SwiftMailer website if a gold mine of documentation and tutorials.
And of course, the full API reference is available if you need it.
If you find a typo or an error, please register and open a ticket.
If you need support or have a technical question, please post to the user mailing-list or to the forum.