You are browsing the Symfony 4 documentation, which changes significantly from Symfony 3.x. If your app doesn't use Symfony 4 yet, browse the Symfony 3.4 documentation.

How to Test that an Email is Sent in a Functional Test

4.1 version
Maintained Unmaintained

How to Test that an Email is Sent in a Functional Test

Sending emails with Symfony is pretty straightforward thanks to the SwiftmailerBundle, which leverages the power of the Swift Mailer library.

To functionally test that an email was sent, and even assert the email subject, content or any other headers, you can use the Symfony Profiler.

Start with a simple controller action that sends an email:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public function sendEmail($name, \Swift_Mailer $mailer)
{
    $message = (new \Swift_Message('Hello Email'))
        ->setFrom('send@example.com')
        ->setTo('recipient@example.com')
        ->setBody('You should see me from the profiler!')
    ;

    $mailer->send($message);

    return $this->render(...);
}

In your functional test, use the swiftmailer collector on the profiler to get information about the messages sent on the previous request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// tests/Controller/MailControllerTest.php
namespace App\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class MailControllerTest extends WebTestCase
{
    public function testMailIsSentAndContentIsOk()
    {
        $client = static::createClient();

        // enables the profiler for the next request (it does nothing if the profiler is not available)
        $client->enableProfiler();

        $crawler = $client->request('POST', '/path/to/above/action');

        $mailCollector = $client->getProfile()->getCollector('swiftmailer');

        // checks that an email was sent
        $this->assertSame(1, $mailCollector->getMessageCount());

        $collectedMessages = $mailCollector->getMessages();
        $message = $collectedMessages[0];

        // Asserting email data
        $this->assertInstanceOf('Swift_Message', $message);
        $this->assertSame('Hello Email', $message->getSubject());
        $this->assertSame('send@example.com', key($message->getFrom()));
        $this->assertSame('recipient@example.com', key($message->getTo()));
        $this->assertSame(
            'You should see me from the profiler!',
            $message->getBody()
        );
    }
}

Troubleshooting

Problem: The Collector Object Is null

The email collector is only available when the profiler is enabled and collects information, as explained in How to Use the Profiler in a Functional Test.

Problem: The Collector Doesn't Contain the Email

If a redirection is performed after sending the email (for example when you send an email after a form is processed and before redirecting to another page), make sure that the test client doesn't follow the redirects, as explained in Testing. Otherwise, the collector will contain the information of the redirected page and the email won't be accessible.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.