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_passwordPour 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.












Commentaires