Blog de Web Omega

Créer un service pour l’envoi de mails avec Symfony2

Envoyer un mail avec Symfony.

Service Mail Symfony

Lors du développement d’un projet, on est souvent confronté à l’envoi de mails multiples à plusieurs moments du déroulement de l’application.

Il est très aisé de comprendre cette problématique, lors de la gestion d’utilisateurs par exemple.

En effet vous devrez envoyer un mail à un utilisateur précis, lorsque vous bloquerez son compte, que vous refusez un de ses articles, ou au contraire lorsque vous acceptez un de ses articles et que vous souhaitez lui notifier cela par mail.

Vous l’aurez compris, les possibilités sont multiples et lorsqu’il s’agit d’effectuer des envois mails pour des dizaines d’actions différentes, cela peut vraiment devenir redondant. De plus, si un jour vous souhaitez changer le nom de votre site, le titre des mails, etc… Qu’en sera-t-il ? La réponse est simple, avec une application standard de la documentation officielle vous devriez aller dans tous vos contrôleurs pour modifier les informations voulues, et ne parlons pas de la perte de temps et des ressources gaspillées.

Je vais donc vous expliquer comment, en quelques étapes simples, mettre en place un service dédié à l’envoi de mails dans Symfony2, vous simplifiant toutes ces tâches.

Étape 1 : Créer une classe d’envoi de mail

Avant de déclarer un service dans Symfony2, il faut créer la classe à laquelle il va faire référence.

Nous allons donc créer une classe Mailer dans notre Bundle, nous pouvons par exemple créer un répertoire « Service » qui va contenir cette classe.

[php]
// /Acme/BlogBundle/Services/Mailer.php

namespace Acme\BlogBundle\Services;

use Symfony\Component\Templating\EngineInterface;

class Mailer
{
protected $mailer;
protected $templating;
private $from = "no-reply@example.fr";
private $reply = "contact@example.fr";
private $name = "Equipe Acme Blog";

public function __construct($mailer, EngineInterface $templating)
{
$this->mailer = $mailer;
$this->templating = $templating;
}

protected function sendMessage($to, $subject, $body)
{
$mail = \Swift_Message::newInstance();

$mail
->setFrom($this->from,$name)
->setTo($to)
->setSubject($subject)
->setBody($body)
->setReplyTo($this->reply,$name)
->setContentType(‘text/html’);

$this->mailer->send($mail);
}
}
[/php]

Comme vous pouvez le voir, dans cette classe nous avons plusieurs choses importantes :
La première est l’importation des espaces de nommage des services tiers que nous allons utiliser :

[php]
use Symfony\Component\Templating\EngineInterface;
[/php]

Vous l’aurez compris, cet import va servir au templating.

Nous allons ensuite instancier quelques variables qui nous seront utiles par la suite.

La troisième chose importante est le constructeur : comme vous le voyez, nous attendons ici deux paramètres, « mailer » et « templating » que nous instancions par la suite.

Étape 2 : Créer nos méthodes de personnalisation de mails

Nous allons ensuite créer des méthodes pour nos envois de mails, par exemple pour envoyer un mail de refus.

[php]
// /Acme/BlogBundle/Services/Mailer.php
public function sendRefusMessage(\Acme\BlogBundle\Entity\User $user){
$subject = "Votre annonce à été refusée";
$template = ‘AcmeBlogBundle:Mail:refus.html.twig’;
$to = $user->getEmail();
$body = $this->templating->render($template, array(‘user’ => $user));
$this->sendMessage($to, $subject, $body);
}
[/php]

Comme vous pouvez le voir c’est très simple et très flexible. De plus, n’oubliez pas que l’avantage de cette solution est de centraliser tous vos envois de mails pour une gestion plus efficace et rapide. De ce fait, lorsque vous modifierez une information dans l’une des méthodes que vous aurez créées, c’est tous les envois de mails s’y rapportant que vous modifierez.

Étape 3 : Déclarer notre classe en tant que service

Dans votre bundle, modifiez le fichier Resources/config/services.xml, et ajoutez les lignes suivantes (si vous utilisez le format yml, adaptez-le à ce dernier.) :

[xml]
// /Acme/BlogBundle/Resources/config/services.xml
<parameters>
<parameter key="acme.mailer.class">Acme\BlogBundle\Services\Mailer</parameter>
</parameters>
<services>
<service id="acme.mailer" class="%acme.mailer.class%">
<argument type="service" id="mailer" />
<argument type="service" id="templating" />
</service>
</services>
[/xml]

Ici nous déclarons notre service, comme vous le voyez, celui-ci sera utilisable grâce au nom « acme.mailer ». Vous pouvez également voir que nous injectons les services mailer et templating.
Attention, le service mailer est un service fourni par Symfony2 et ne correspond pas du tout à celui que vous venez de créer.

Étape 4 : Utiliser notre service

Ça y est c’est fait vous n’avez plus qu’à utiliser votre service et à gagner un temps considérable, vous pouvez l’appeler comme ci-dessous dans tous vos contrôleurs :

[php]
$this->get(‘acme.mailer’)->sendRefusMessage($user);
[/php]

Astuces

Lors de phases de test il peut être très embêtant d’envoyer des mails réels, vous pouvez donc désactiver l’envoi de mail pour la production en modifiant ou en ajoutant la ligne suivante dans votre fichier de config :

[php]
// /app/config/config_dev.yml
swiftmailer:
disable_delivery: false
[/php]

Le seul désavantage est que vous ne pourrez plus voir votre mail dans votre profiler si vous effectuez une redirection. Heureusement Symfony2 fournit une option qui permet d’intercepter la redirection et donc de voir si votre mail s’est bien envoyé. Ça se passe par ici :

[php]
// /app/config/config_dev.yml
web_profiler:
intercept_redirects: true
[/php]

Steeve Audoli – Web Developer