Skip to content

[Mailer] HTML-Mail with TWIG Template and async transport #44439

@swnjfn

Description

@swnjfn

Symfony version(s) affected

5.*

Description

Trying to send a html mail with twig template (https://symfony.com/doc/current/mailer.html#html-content) with async transport (https://symfony.com/doc/current/mailer.html#sending-messages-async).

use Symfony\Bridge\Twig\Mime\TemplatedEmail;

$email = (new TemplatedEmail())
    ->from('fabien@example.com')
    ->to(new Address('ryan@example.com'))
    ->subject('Thanks for signing up!')

    // path of the Twig template to render
    ->htmlTemplate('emails/signup.html.twig')

    // pass variables (name => value) to the template
    ->context([
        'expiration_date' => new \DateTime('+7 days'),
        'username' => 'foo',
    ])
;

How to reproduce

The Problem occure in my case when putting an entity in the context of the mail object

use Symfony\Bridge\Twig\Mime\TemplatedEmail;

$email = (new TemplatedEmail())
    ->from('fabien@example.com')
    ->to(new Address('ryan@example.com'))
    ->subject('Thanks for signing up!')

    // path of the Twig template to render
    ->htmlTemplate('emails/signup.html.twig')

    // pass variables (name => value) to the template
    ->context([
        'entity' => $this->someServiceToGetTheEnttiy->getMyImportantEntity()
    ])
;

In my case there are some ORM-Mapping (Many to...) to other Entities. Finally one of the mapped entities has an Symfony\Component\HttpFoundation\File in the property.

Symfony\Component\Messenger\Transport\Serialization\PhpSerializer:encode() uses

$body = addslashes(serialize($envelope));

which will throw an exception, because Symfony\Component\HttpFoundation\File is not allowed to serialize (could also happen with other stuff).

This Example is really just an example, but i actually will parse an entity to the twig template by mail->context().
This is not a szenario what will be often occure i think. But perhaps someone has an similar issue.

Possible Solution

  1. Only use informations and object that you really need in the context (so an Entity is a bad idea)

  2. Throw context out of the envelop object befor sending it

use Symfony\Bridge\Twig\Mime\TemplatedEmail;

$email = (new TemplatedEmail())
    ->from('fabien@example.com')
    ->to(new Address('ryan@example.com'))
    ->subject('Thanks for signing up!')

    // path of the Twig template to render
    ->htmlTemplate('emails/signup.html.twig')

    // pass variables (name => value) to the template
    ->context([
        'expiration_date' => new \DateTime('+7 days'),
        'username' => 'foo',
    ])
;

// this could be done by an mail service otherwise just do it directly without setting templates to the `TemplatedMail`-Object
// $this->twig is the `Twig\Environment` injection in this service

if ($email->getTextTemplate()) {
    $email->text($this->twig->render($mail->getTextTemplate(), $email->getContext()));
    $email->textTemplate(null); // musst be set to null or the mailer will try to render this again
}
if ($email->getHtmlTemplate()) {
    $bodyRenderer = new Symfony\Bridge\Twig\Mime\BodyRenderer($this->twig);
    $bodyRenderer->render($email);
    $email->htmlTemplate(null); // musst be set to null or the mailer will try to render this again
}

$email->context([]);

$this->mailService->send($email);






### Additional Context

_No response_

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions