Caution: You are browsing the legacy Logo of the legacy symfony 1 version 1.x part of this website.
This version of symfony is not maintained anymore. If some of your projects still use this version, consider upgrading.

Master Symfony fundamentals

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
training.sensiolabs.com

Discover SensioLabs' Professional Business Solutions

Peruse our complete Symfony & PHP solutions catalog for your web development needs.
sensiolabs.com

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 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.

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.