Aller au contenu | Aller au menu | Aller à la recherche

Site membre du réseau Izardev et LCNET

Symfony2 : SMTP et SwiftMailer

L'envoi de mail est bien souvent nécessaire à la majorité des applications web, cependant, on peut vouloir envoyer des mails à la volée avec des paramètres différents selon la nature du message.

Pré-requis

Il ne faut pas oublier d'activer le bundle livré avec symfony, SwiftMailer dans appKernel.php

public function registerBundles()
{
    $bundles = array(
        new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
    );
}

L'envoi de mail classique

Ce type d'envoi est bien expliqué dans le cookbook symfony2 ( http://symfony.com/doc/2.0/cookbook/email/email.html ), Dans le fichier config.yml, on définit les paramètres par défaut :

# app/config/config.yml
swiftmailer:
    transport:  smtp
    encryption: ssl # ssl, tls
    auth_mode:  login # login, plain ou cram-md5
    host:       smtp.ligams.com
    username:   your_username
    password:   your_password

Pour utiliser cette configuration par défaut et envoyer un email, il suffit d'instancier un objet Swift_Message que l'on enverra avec le service mailer :

namespace Newsfree\EmailBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class FooController extends Controller 
{
    public function indexAction(){
        $message = \Swift_Message::newInstance();
        $message->setSubject("Objet");
        $message->setFrom('ligamsATligams.com');
        $message->setTo('destinataire@domaine.com');
        // pour envoyer le message en HTML
        $message->setBody('Hello world');
        // pour envoyer le message en HTML
        $message->setBody('<p>Hello world</p>','text/html'); 
        //envoi du message
         $this->get('mailer')->send($message);
     }
}

Ainsi, vous utilisez les paramètres par défaut.

Modifier les paramètres d'envoi de mail à la volée

Vous ne pouvez peut être pas utiliser ces paramètres d'envoi systématiquement : vous devez alors changer créer de nouveaux paramètres à la volée : attention, si vous ne passez pas de 3e paramètres (ou null) en instanciant Swift_SmtpTransport, les méthodes setUsername et setPassword seront indéfinies (undefined method setUsernam) car aucune authentification n'est prévue :

namespace Newsfree\EmailBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class FooController extends Controller 
{
    public function indexAction(){
        //création d'un objet transport
        $transport = \Swift_SmtpTransport::newInstance('smtp.ligams.com', 25, 'ssl' )
                        ->setUsername('username')
                        ->setPassword('password');
        //création d'un objet mailer
        $mailer = \Swift_Mailer::newInstance($transport);
        $message = \Swift_Message::newInstance();
        $message->setSubject("Objet");
        $message->setFrom('ligamsATligams.com');
        $message->setTo('destinataire@domaine.com');
        // pour envoyer le message en HTML
        $message->setBody('Hello world');
        // pour envoyer le message en HTML
        $message->setBody('<p>Hello world</p>','text/html'); 
        //envoi du message
        $mailer->send($message);
     }
}

Envoi de mails en masse et personnalisation

C'est bien joli tout ça, mais dans un monde réel, on a besoin de personnaliser les messages et d'envoyer en masse ( bulk mails ), c'est pourquoi je vais aborder l'utilisation des plugins pour SwiftMailer suivants que je trouve particulièrement utiles :

  • Swift_Plugins_DecoratorPlugin : Decorator va servir à personnaliser chaque message que vous allez envoyer dans une boucle, en remplaçant des tags que vous allez définir par des valeurs propres à chaque mails (en général, nom, prénom, identifiant quelconque...)
  • Swift_Plugins_AntiFloodPlugin : comme son nom l'indique... les serveurs smtp se protègent souvent contre l'envoi massif, le plugin antiflood permet d'atténuer volontairement les envois afin de ne pas offenser les serveurs smtp.
  • Swift_Plugins_ThrottlerPlugin : Un petit peu comme antiflood, il permet par exemple de définir un maximum d'envoi par minute, et un maximum de transit par minute.

Utilisons les 3 à la fois dans un exemple, imaginons un tableau $users comparable au résultat d'un findAll() avec fos_user :

<?php
namespace Newsfree\EmailBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class FooController extends Controller 
{
    public function indexAction(){
        //...
        //création d'un objet transport
        $transport = \Swift_SmtpTransport::newInstance('smtp.ligams.com', 25, 'ssl' )
                        ->setUsername('username')
                        ->setPassword('password');
        //création d'un objet mailer
        $mailer = \Swift_Mailer::newInstance($transport);
        
        /**
         * Création des objets de plugin
         */
        //maximum 1000 mails par minute
        $throttle = new \Swift_Plugins_ThrottlerPlugin(1000, \Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE);
        //maximum 30 mégas de mails par minute
        $throttle2 = new \Swift_Plugins_ThrottlerPlugin(1024*1024*30, \Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE);
        // une seconde de pause tous les 100 mails
        $antiflood = new \Swift_Plugins_AntiFloodPlugin(100,1); 

        foreach($users as $user)
        {
            $decoratorReplacement[$user->email] = array(
               '#email#' => $user->email,
               '#nom#'   => $user->nom,
               '#prenom#'=> $user->prenom,
           );
            
        }
        
        $decorator = new \Swift_Plugins_DecoratorPlugin($decoratorReplacement);
        //on enregistre les plugins
        $mailer->registerPlugin($antiflood);
        $mailer->registerPlugin($throttle);
        $mailer->registerPlugin($throttle2);
        $mailer->registerPlugin($decorator);
        
        $message = \Swift_Message::newInstance();
        $message->setSubject("Objet : #nom# #prenom#");
        $message->setFrom('ligamsATligams.com');
        $message->setBody('<p>Hello #nom# #prenom# #email#</p>','text/html'); 
        foreach($users as $user){
            $message->setTo($user->email);
            if(!$mailer->send($message)){
              //erreur d'envoi
           }
        }
     }
}

Voilà, ça couvre à peu près tous les besoins, pour l'envoi de masse, il est possible d'utiliser un spooler de mail livré avec symfony2, ou de créer une commande (php app/console ...), il reste malvenu de placer des envois d'email de masse (newsletter) dans un contrôleur.

Articles connexes

Partagez cet article !

  • Delicious
  • Stumbleupon
  • Digg
  • Facebook
  • Google
  • Linkedin
  • Yahoo Buzz
  • Twitter
Vous avez apprécié cet article ?

Commentaires S'abonner au flux RSS des commentaires

Ajouter un commentaire

Les commentaires sont tous validés par un modérateur, votre commentaire n'apparaît pas directement sur le site.
Aucun support n'est assuré ici, vous pouvez néanmoins laisser vos remarques et critiques sur l'article, les points de vue pertinents sont toujours les bienvenus.