Creating, Configuring & Sending the Email Object

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Time to send... an email! After a user registers for a new account, we should probably send them a welcome email. The controller for this page lives at src/Controller/SecurityController.php... find the register() method.

This is a very traditional controller: it creates a Symfony form, processes it, saves a new User object to the database and ultimately redirects when it finishes.

Let's send an email right here: right after the user is saved, but before the redirect. How? It's gorgeous. Start with $email = (new Email()) - the one from the Mime namespace.

... lines 1 - 10
use Symfony\Component\Mime\Email;
... lines 12 - 16
class SecurityController extends AbstractController
{
... lines 19 - 46
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder, GuardAuthenticatorHandler $guardHandler, LoginFormAuthenticator $formAuthenticator)
{
... lines 49 - 51
if ($form->isSubmitted() && $form->isValid()) {
... lines 53 - 70
$em->flush();
$email = (new Email())
... lines 74 - 84
}
... lines 86 - 89
}
}

Mime & Mailer Components

Actually, this is a good moment to mention that when we talk about the Mailer component in Symfony, we're actually talking about two components: Mailer and Mime. The Mime component is all about creating & configuring the email itself and Mailer is all about sending that email. But mostly... that's not too important: just don't be surprised when you're using objects from this Mime namespace.

Configuring the Email

I've put the new Email object in parentheses on purpose: it allows us to immediately chain off of this to configure the message. Pretty much all the methods on the Email class are... delightfully boring & familiar. Let's set the ->from() address to, how about, alienmailer@example.com, the ->to() to the address of the user that just registered - so $user->getEmail() - and this email needs a snazzy subject!

Welcome to the Space Bar!

... lines 1 - 10
use Symfony\Component\Mime\Email;
... lines 12 - 16
class SecurityController extends AbstractController
{
... lines 19 - 46
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder, GuardAuthenticatorHandler $guardHandler, LoginFormAuthenticator $formAuthenticator)
{
... lines 49 - 72
$email = (new Email())
->from('alienmailcarrier@example.com')
->to($user->getEmail())
->subject('Welcome to the Space Bar!')
... lines 77 - 89
}
}

Pure poetry. Finally, our email needs content! If you've sent emails before, then you might know that an email can have text content, HTML content or both. We'll talk about HTML content soon. But for now, let's set the ->text() content of the email to:

Nice to meet you

And then open curly close curly, $user->getFirstName(), and, of course, a ❤️ emoji.

... lines 1 - 10
use Symfony\Component\Mime\Email;
... lines 12 - 16
class SecurityController extends AbstractController
{
... lines 19 - 46
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder, GuardAuthenticatorHandler $guardHandler, LoginFormAuthenticator $formAuthenticator)
{
... lines 49 - 72
$email = (new Email())
->from('alienmailcarrier@example.com')
->to($user->getEmail())
->subject('Welcome to the Space Bar!')
->text("Nice to meet you {$user->getFirstName()}! ❤️");
... lines 78 - 89
}
}

There are a bunch more methods on this class, like cc(), addCc(), bcc() and more... but most of these are dead-easy to understand. And because it's such a simple class, you can look inside to see what else is possible, like replyTo(). We'll talk about many of these - like attaching files - later.

So... that's it! That's what it looks like to create an email. I hope this "wow'ed" you... and disappointed you in its simplicity... all at the same time.

Sending the Email

Ok... so now... how do we send this email? As soon as we installed the Mailer component, Symfony configured a new mailer service for us that we can autowire by using - surprise! - the MailerInterface type-hint.

Let's add that as one of the arguments to our controller method: MailerInterface $mailer.

... lines 1 - 10
use Symfony\Component\Mailer\MailerInterface;
... lines 12 - 17
class SecurityController extends AbstractController
{
... lines 20 - 47
public function register(MailerInterface $mailer, Request $request, UserPasswordEncoderInterface $passwordEncoder, GuardAuthenticatorHandler $guardHandler, LoginFormAuthenticator $formAuthenticator)
{
... lines 50 - 92
}
}

And... what methods does this object have on it? Oh, just one: $mailer->send() and pass this $email.

... lines 1 - 10
use Symfony\Component\Mailer\MailerInterface;
... lines 12 - 17
class SecurityController extends AbstractController
{
... lines 20 - 47
public function register(MailerInterface $mailer, Request $request, UserPasswordEncoderInterface $passwordEncoder, GuardAuthenticatorHandler $guardHandler, LoginFormAuthenticator $formAuthenticator)
{
... lines 50 - 52
if ($form->isSubmitted() && $form->isValid()) {
... lines 54 - 73
$email = (new Email())
->from('alienmailcarrier@example.com')
->to($user->getEmail())
->subject('Welcome to the Space Bar!')
->text("Nice to meet you {$user->getFirstName()}! ❤️");
$mailer->send($email);
... lines 81 - 87
}
... lines 89 - 92
}
}

I love how this looks. But... will it work? We haven't actually configured how emails should be sent but... ah, let's just see what happens. Move over and register: first name Fox (last name, Mulder, in case you're wondering), email: thetruthisoutthere@example.com, any password, agree to the terms that we definitely read and, register!

Ah! Error!

Environment variable not found: MAILER_DSN

Ok, fine! To actually deliver emails, we need to add some configuration via this environment variable. Let's talk about that next... including some awesome options for debugging emails while you're developing.

Leave a comment!

This tutorial is built on Symfony 4.3, but will work well with Symfony 4.4 or 5.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "aws/aws-sdk-php": "^3.87", // 3.110.11
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-snappy-bundle": "^1.6", // v1.6.0
        "knplabs/knp-time-bundle": "^1.8", // v1.9.1
        "league/flysystem-aws-s3-v3": "^1.0", // 1.0.23
        "league/flysystem-cached-adapter": "^1.0", // 1.0.9
        "league/html-to-markdown": "^4.8", // 4.8.2
        "liip/imagine-bundle": "^2.1", // 2.1.0
        "nexylan/slack-bundle": "^2.1,<2.2.0", // v2.1.0
        "oneup/flysystem-bundle": "^3.0", // 3.1.0
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.4.1
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.3.4
        "symfony/console": "^4.0", // v4.3.4
        "symfony/flex": "^1.9", // v1.9.10
        "symfony/form": "^4.0", // v4.3.4
        "symfony/framework-bundle": "^4.0", // v4.3.4
        "symfony/mailer": "4.3.*", // v4.3.4
        "symfony/messenger": "4.3.*", // v4.3.4
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.3.4
        "symfony/sendgrid-mailer": "4.3.*", // v4.3.4
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "^4.0", // v4.3.4
        "symfony/twig-pack": "^1.0", // v1.0.0
        "symfony/validator": "^4.0", // v4.3.4
        "symfony/web-server-bundle": "^4.0", // v4.3.4
        "symfony/webpack-encore-bundle": "^1.4", // v1.6.2
        "symfony/yaml": "^4.0", // v4.3.4
        "twig/cssinliner-extra": "^2.12", // v2.12.0
        "twig/extensions": "^1.5", // v1.5.4
        "twig/inky-extra": "^2.12" // v2.12.0
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.2.2
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/browser-kit": "4.3.*", // v4.3.5
        "symfony/debug-bundle": "^3.3|^4.0", // v4.3.4
        "symfony/dotenv": "^4.0", // v4.3.4
        "symfony/maker-bundle": "^1.0", // v1.13.0
        "symfony/monolog-bundle": "^3.0", // v3.4.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.3.4
        "symfony/profiler-pack": "^1.0", // v1.0.4
        "symfony/var-dumper": "^3.3|^4.0" // v4.3.4
    }
}