Tester une connexion SMTP avec SwiftMailer

J'ai pour habitude de créer une page de statut dans les applications que je développe afin de tester que l'ensemble des services nécessaires au bon fonctionnement de cette dernière (base de données, serveur mail, API...) sont lancés et correctement configurés. Nous allons voir dans cet article comment tester une connexion SMTP au sein d'une application utilisant le composant SwiftMailer.

Si l'on prend le cas d'usage simple proposé en introduction dans la documentation du composant :

// Create the Transport
$transport = (new Swift_SmtpTransport('smtp.example.org', 25))
  ->setUsername('your username')
  ->setPassword('your password')
;

// Create the Mailer using your created Transport
$mailer = new Swift_Mailer($transport);

// Create a message
$message = (new Swift_Message('Wonderful Subject'))
  ->setFrom(['john@doe.com' => 'John Doe'])
  ->setTo(['receiver@domain.org', 'other@domain.org' => 'A name'])
  ->setBody('Here is the message itself')
  ;

// Send the message
$result = $mailer->send($message);

Le principe pour une connexion est simple, il faut tester que la couche transport puisse se connecter au service. Pour cela, il faut démarrer la connexion vers le serveur SMTP et vérifier si une erreur s'est produite :

try {
    $transport->start();
    $isSmtpOk = true;
} catch (Swift_TransportException $e) {
    $isSmtpOk = false;
}

L'exemple ci-dessus marche bien, mais dans la plupart des cas, nous envoyons rarement directement un mail. Dans une grande majorité des cas, nous allons utiliser un spool de mail qui va stocker les mails que l'on souhaite envoyer pour par la suite effectuer un traitement en lot. C'est par exemple, le fonctionnement par défaut de SwiftMailer dans Symfony.

$spool = new FileSpool(__DIR__.'/var/spool');
$transport = new Swift_SpoolTransport($spool);
$mailer = new Swift_Mailer($transport);

Or dans ce cas, on ne peut pas réellement tester la couche de transport directement car notre instance de la classe Swift_SpoolTransport ne gère pas réellement l'envoi des mails, mais gère la logique permettant de traiter le mail plus tard. De ce fait l' implémentation de la méthode $transport->start() est vide et ne fait donc aucune action.

Il faudra donc dans ce cas, tester la méthode start directement sur l'instance du spool, à savoir sur notre objet $spool. Et si vous utilisez Symfony, le framework configure un service swiftmailer.transport.real permettant d'accéder à l'instance de l'objet qui gérera réellement l'envoi des mails.