Le driver email failover

Publié le 21 mars 2024 par Antoine Benevaut
Couverture de l'article Le driver email failover

Si votre application a de fort enjeux sur la délivrabilité de vos communications mails, vous êtes probablement à la recherche d'une solution afin de ne pas subir les dysfonctionnements de votre prestataire e-mail.

Comme tous services informatiques, les prestataires de services mails ne sont pas infaillibles et peuvent faire face à des interruptions de service.

Dans ce cas, votre activité en pâtit immédiatement et les interactions avec vos utilisateurs sont ralenties, les tickets de supports pleuvent.

Heureusement, Laravel est équipé du driver "failover" permettant de définir des prestataires de secours pour ne jamais manquer l'émission d'un e-mail.

Passons à l'action !

Nous allons mettre en place ensemble un failover pour deux prestataires mails que nous simulerons avec MailHog (il vous faudra donc l'outil sur votre poste de travail).

Pour les amateurs de Docker, vous trouverez, à ce lien, un fichier docker-compose prêt à l'emploi.

Sur votre machine, lancer le premier service MailHog sans aucune option particulière, le serveur mail SMTP sera disponible sur localhost:1025 et l'interface du webmail sur localhost:8025.

Nous pouvons maintenant ajouter un "mailer" nommé "mailhog" dans la configuration Laravel (le fichier mail.php).

Là encore, aucune configuration particulière, si ce n'est le port SMTP à préciser.

1<?php
2 
3return [
4 'default' => env('MAIL_MAILER', 'production'),
5 'mailers' => [
6 
7 'mailhog' => [
8 'transport' => 'smtp',
9 'host' => '127.0.0.1',
10 'port' => 1025,
11 'encryption' => null,
12 'username' => null,
13 'password' => null,
14 'timeout' => null,
15 'local_domain' => null,
16 ],
17 
18 ],
19 // ..
20];

Une fois configuré, nous pouvons nous lancer dans la création minimaliste d'une notification pour nous assurer du bon fonctionnement du service mail.

Dans une commande ou dans un controller, vous pouvez utiliser le code qui suit, il faudra également penser à régler le mailer de l'application sur notre mailer "mailhog", dans votre .env en modifiant la variable MAIL_MAILER="mailhog".

1<?php
2 
3use Illuminate\Mail\Message;
4use Illuminate\Support\Facades\Mail;
5 
6Mail::raw('Hello world', function (Message $message) {
7 $message->to('receiver@failover.com')->from('sender@failover.com');
8});

Super ! nous recevons bien notre e-mail !

Simuler une défaillance

Nous allons maintenant simuler une défaillance de notre serveur Mailhog, cette simulation peut être utile pour vérifier que vos utilisateurs ne sont pas bloqués lors de ces interruptions de service et aussi pour s'assurer que votre système de logs récupère ces exceptions.

Pour cela, MailHog dispose d'un outil sous le doux nom de Jim permettant de simuler aléatoirement des pannes lors de la réception d'un e-mail par le serveur.

Pour initialiser Jim, nous allons lancer MailHog avec des arguments supplémentaires :

1MailHog \
2 -invite-jim \ # Initialise Jim au lancement de MailHog
3 -jim-accept=0.4 # Indique que Jim permet la bonne reception des mails 40% du temps

Attention ! Nous lançons une seconde instance de MailHog, celle-ci ne pourra s'exécuter avec les mêmes ports que la précédente, voici les arguments qui vous permettront de les changer.

1MailHog \
2 -smtp-bind-addr=0.0.0.0:1026 \
3 -ui-bind-addr=0.0.0.0:8026 \
4 -api-bind-addr=0.0.0.0:8026

Une fois de plus, nous ajouterons un mailer supplémentaire, ici, il a le nom "mailhogWithJim" et l'on fera attention à bien reporter le port choisit précédemment.

1<?php
2 
3return [
4 'default' => env('MAIL_MAILER', 'production'),
5 'mailers' => [
6 
7 'mailhog' => [
8 // [...]
9 ],
10 
11 'mailhogWithJim' => [
12 'transport' => 'smtp',
13 'host' => '127.0.0.1',
14 'port' => 1026,
15 'encryption' => null,
16 'username' => null,
17 'password' => null,
18 'timeout' => null,
19 'local_domain' => null,
20 ],
21 
22 ],
23 // ..
24];

En modifiant une nouvelle fois la variable d'environnement MAIL_MAILER avec la valeur de ce mailer ("mailhogWithJim") vous pourrez re-exécuter le test précédent.

En le lançant plusieurs fois successives, vous devrez voir apparaître des erreurs sur votre application Laravel, MailHog ne reçoit effectivement pas correctement tous les mails, via l'interface web.

Nous avons nos deux services configurés, nous pouvons nous atteler au driver "failover".

Grâce à ce driver, nous allons pouvoir absorber les défaillances de notre service MailHog - avec Jim - via notre second service MailHog.

Pour ce faire, nous allons créer un troisième et dernier mailer dans la configuration Laravel. Dans la chaîne du "failover", nous essaierons d'envoyer nos mails avec le mailer "mailhogWithJim" et en cas d'échec, c'est le mailer "mailhog" qui prendra le relais pour envoyer nos e-mails.

1<?php
2 
3return [
4 'default' => env('MAIL_MAILER', 'production'),
5 'mailers' => [
6 
7 'mailhog' => [
8 // [...]
9 ],
10 
11 'mailhogWithJim' => [
12 // [...]
13 ],
14 
15 'local' => [
16 'transport' => 'failover',
17 'mailers' => [
18 'mailhogWithJim',
19 'mailhog',
20 ],
21 ],
22 
23 ],
24 // ..
25];

En modifiant une dernière fois la variable d'environnement MAIL_MAILER avec la valeur de ce mailer "failover" (nommé "local") vous pourrez re-exécuter le test précedent.

Cette fois-ci, après des envois successifs, vous pourrez voir des mails arrivés dans les deux interfaces web des deux services MailHog, mission accomplie !

En cas d'échec d'un prestataire, nos mails trouveront tout de même leur chemin pour parvenir jusqu'aux boîtes mail de nos utilisateurs.

Pour conclure, sachez que vous pouvez utiliser toute sorte de drivers dans la liste des mailers du driver "failover" et ce pourrait être une bonne idée d'utiliser le driver "log" comme dernier maillon de cette chaîne de "failover" pour qu'en dernier recours, vous puissiez être averti de l'échec de l'ensemble de vos prestataires le cas échéant.

Source : https://gist.github.com/abenevaut/0c0dec362aed94b73f829a13e99b58b1
Antoine Benevaut avatar
Antoine Benevaut
PHP and Laravel Consultant

A lire

Autres articles de la même catégorie