Aller au contenu principal

Le composant Mailer de Symfony

Comment envoyer des e-mails depuis une application Symfony grâce au composant Mailer et au service MailerInterface

Notions théoriques

Le composant Mailer

Beaucoup d'applications ont besoin d'envoyer des e-mails : confirmation d'inscription, réinitialisation de mot de passe, notification... Symfony fournit pour cela son propre composant, Mailer, intégré au conteneur de services et à Twig.

remarque

Vous avez déjà croisé une bibliothèque d'envoi d'e-mails en PHP procédural : PHPMailer. C'est une bibliothèque générique, indépendante de tout framework. Le composant Mailer de Symfony joue le même rôle, mais s'intègre nativement au conteneur de services, à la configuration par variables d'environnement et à Twig — exactement comme les autres composants que vous utilisez déjà dans vos projets Symfony.

Installation et configuration

On installe le composant avec Composer :

composer require symfony/mailer

La configuration se fait via une seule variable d'environnement dans le fichier .env : MAILER_DSN. Ce DSN (Data Source Name) décrit comment se connecter au serveur d'envoi (SMTP, service tiers...).

.env
# Exemple avec un serveur SMTP classique
MAILER_DSN=smtp://user:password@smtp.example.com:587
attention

Comme pour la connexion à la base de données, ne jamais committer de véritables identifiants SMTP dans le fichier .env versionné. On place les vraies valeurs dans .env.local, qui reste hors de Git.

Créer et envoyer un e-mail simple

La classe Email représente un e-mail : expéditeur, destinataire, sujet et contenu. On l'envoie grâce au service MailerInterface, injecté comme n'importe quel autre service.

use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;

public function envoyerBienvenue(MailerInterface $mailer): void
{
$email = (new Email())
->from('contact@monblog.fr')
->to('nouvel.utilisateur@example.com')
->subject('Bienvenue sur le blog !')
->text('Merci de vous être inscrit.')
->html('<p>Merci de vous être <strong>inscrit</strong>.</p>');

$mailer->send($email);
}

Utiliser un template Twig avec TemplatedEmail

Écrire le contenu HTML d'un e-mail directement dans le code PHP devient vite difficile à maintenir. Symfony propose la classe TemplatedEmail, qui délègue le corps de l'e-mail à un template Twig, exactement comme on le fait déjà pour une page web classique.

use Symfony\Bridge\Twig\Mime\TemplatedEmail;

$email = (new TemplatedEmail())
->from('contact@monblog.fr')
->to($utilisateur->getEmail())
->subject('Bienvenue sur le blog !')
->htmlTemplate('emails/bienvenue.html.twig')
->context([
'pseudo' => $utilisateur->getPseudo(),
]);

$mailer->send($email);

Le template Twig reçoit les variables passées dans context(), comme n'importe quel template rendu par un contrôleur :

templates/emails/bienvenue.html.twig
<p>Bonjour {{ pseudo }},</p>
<p>Merci de vous être inscrit sur le blog !</p>
info

Un TemplatedEmail peut définir à la fois un template pour la version HTML et un template pour la version texte brut, avec htmlTemplate() et textTemplate(). Cela garantit un affichage correct même sur les clients de messagerie qui n'affichent pas le HTML.

Envoi bloquant : une sensibilisation

Par défaut, $mailer->send($email) bloque l'exécution de la requête HTTP jusqu'à ce que l'e-mail soit effectivement transmis au serveur SMTP.

attention

En production, un envoi bloquant ralentit la réponse renvoyée à l'utilisateur, et peut même faire échouer toute la requête si le serveur SMTP est lent ou indisponible. Symfony propose une solution à base de file d'attente (le composant Messenger) pour envoyer les e-mails de façon asynchrone — un sujet qui dépasse le cadre de cette séance, mais qu'il est utile de garder en tête pour vos futurs projets.

Exemple de mise en application

Un cas d'usage très courant : envoyer un e-mail de confirmation juste après l'inscription d'un utilisateur.

// src/Service/InscriptionManager.php
namespace App\Service;

use App\Entity\Utilisateur;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;

class InscriptionManager
{
public function __construct(
private EntityManagerInterface $entityManager,
private MailerInterface $mailer
) {}

public function inscrire(Utilisateur $utilisateur): void
{
$this->entityManager->persist($utilisateur);
$this->entityManager->flush();

$email = (new TemplatedEmail())
->from(new Address('contact@monblog.fr', 'Le Blog'))
->to($utilisateur->getEmail())
->subject('Confirmez votre inscription')
->htmlTemplate('emails/confirmation_inscription.html.twig')
->context([
'pseudo' => $utilisateur->getPseudo(),
]);

$this->mailer->send($email);
}
}
astuce

La classe Address permet d'associer un nom affiché (« Le Blog ») à une adresse e-mail. C'est ce nom qui apparaît dans la boîte de réception du destinataire, plutôt que l'adresse brute.

Test de mémorisation/compréhension


Quelle commande Composer installe le composant Mailer de Symfony ?


Quelle variable d'environnement configure la connexion au serveur d'envoi d'e-mails ?


Quel service Symfony faut-il injecter pour envoyer un e-mail ?


Quelle classe permet de définir le corps d'un e-mail à partir d'un template Twig ?


Quelle méthode envoie effectivement l'e-mail ?


Quelle bibliothèque PHP générique (non spécifique à Symfony) avez-vous déjà étudiée pour l'envoi d'e-mails ?


Où doit-on placer les véritables identifiants SMTP pour ne jamais les committer dans Git ?


Pourquoi faut-il rester prudent avec un envoi d'e-mail bloquant en production ?



TP pour réfléchir et résoudre des problèmes

Votre défi pour aujourd'hui consiste à envoyer un e-mail de bienvenue à chaque nouvel abonné à la newsletter du blog, à partir d'un template Twig.

Étape 1 — Compléter le DSN de configuration

Pour un environnement de développement, on utilise souvent un service local de capture d'e-mails.

Étape 2 — Injecter le service MailerInterface

Le service AbonneNewsletterManager doit recevoir le service d'envoi de mails par injection de dépendance.


Bonne pratique - Injecter MailerInterface plutôt que Mailer

Toujours injecter l'interface (MailerInterface) et non une implémentation concrète. C'est le principe déjà rencontré avec les repositories et les services : dépendre d'une interface permet à Symfony de choisir l'implémentation adéquate, et facilite les tests (on peut simuler l'interface sans envoyer de vrais e-mails pendant les tests automatisés).

Étape 3 — Construire et envoyer le TemplatedEmail

Après avoir enregistré l'abonné en base, il faut construire l'e-mail de bienvenue à partir du template emails/bienvenue_newsletter.html.twig et l'envoyer.


Bonne pratique - Envoyer l'e-mail après le flush()

Exactement comme pour dispatcher un événement métier : on envoie l'e-mail une fois les données réellement enregistrées en base. Si l'inscription échoue avant le flush(), on évite d'envoyer un e-mail de confirmation pour une inscription qui n'a finalement pas eu lieu.

📌 Une solution