En bref — dans une application web, les e-mails transactionnels — vérification d'adresse, code de connexion, mot de passe oublié, confirmation de commande — font partie du parcours utilisateur au même titre qu'un bouton. S'ils n'arrivent pas, ou arrivent en spam, le parcours est cassé. La délivrabilité repose sur trois choses : prouver qu'on a le droit d'envoyer (SPF, DKIM, DMARC), choisir un prestataire dont les choix par défaut ne jouent pas contre vous, et concevoir l'application pour qu'un échec d'envoi ne soit jamais silencieux. Voici comment je m'y prends sur mes projets.
Transactionnel n'est pas marketing
Première distinction, souvent négligée : un e-mail transactionnel est déclenché par une action de l'utilisateur et attendu par lui, dans les secondes qui suivent. Une newsletter est envoyée à l'initiative de l'expéditeur, à une liste. Les deux n'ont ni les mêmes exigences ni les mêmes règles, et les mélanger sur un même domaine et un même compte est une mauvaise idée : une campagne marketing qui génère des plaintes pour spam dégrade la réputation de tout ce qui part du même endroit — codes de connexion compris.
Tout ce qui suit concerne le transactionnel, celui dont dépend le fonctionnement de l'application.
Un sous-domaine d'envoi dédié
Mes domaines principaux ont déjà une messagerie : les adresses de contact y reçoivent et envoient du courrier via un hébergeur mail. Plutôt que de faire cohabiter cette messagerie et l'envoi applicatif sur le même nom de domaine, j'envoie les e-mails applicatifs depuis un sous-domaine dédié — du type send.exemple.fr ou email.exemple.fr.
Les avantages sont concrets. Chaque sous-domaine a ses propres enregistrements SPF et DKIM, donc la configuration de l'envoi applicatif ne touche jamais celle de la messagerie humaine. La réputation est cloisonnée : un incident sur l'un n'entache pas l'autre. Et changer de prestataire d'envoi ne demande de toucher qu'aux enregistrements du sous-domaine, sans risque de casser la réception des e-mails de contact.
SPF, DKIM, DMARC : prouver qu'on a le droit d'envoyer
Le protocole e-mail d'origine ne vérifie pas l'expéditeur : n'importe qui peut écrire From: contact@votre-domaine.fr. Trois mécanismes, tous publiés dans le DNS du domaine, permettent aux messageries destinataires de distinguer vos e-mails de ceux d'un usurpateur. Sans eux, en 2026, vos messages ont toutes les chances d'être refusés ou classés en spam par les grandes messageries.
SPF liste les serveurs autorisés à envoyer pour le domaine. C'est un enregistrement TXT qui délègue généralement au prestataire :
send.exemple.fr. TXT "v=spf1 include:amazonses.com ~all"DKIM signe cryptographiquement chaque message. Le prestataire détient la clé privée ; vous publiez la clé publique sous un « sélecteur », et le destinataire vérifie que le message n'a pas été altéré en route :
resend._domainkey.send.exemple.fr. TXT "p=MIGfMA0GCSqGSIb3DQEB..."DMARC relie les deux au domaine visible dans le champ From — c'est la notion d'alignement — et dit au destinataire quoi faire si la vérification échoue : ne rien faire (p=none), mettre en quarantaine (p=quarantine) ou rejeter (p=reject). Il permet aussi de recevoir des rapports sur les e-mails envoyés en votre nom.
_dmarc.exemple.fr. TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@exemple.fr"Ma démarche : commencer en p=none avec les rapports activés, vérifier pendant quelques jours que tous les envois légitimes passent, puis durcir jusqu'à p=reject. Un domaine en p=reject est un domaine que personne ne peut usurper pour hameçonner vos utilisateurs — et c'est aussi un signal de sérieux pour les messageries.
Pour vérifier le résultat, rien ne vaut un vrai message : on s'envoie un e-mail, on affiche sa source, et on cherche l'en-tête Authentication-Results. Il doit indiquer spf=pass, dkim=pass et dmarc=pass. Tant que ce n'est pas le cas, le reste n'a pas d'importance.
Choisir un prestataire : lire au-delà des tarifs
Les offres d'envoi transactionnel se ressemblent sur le papier : une API, un accès SMTP, une offre gratuite de quelques centaines d'e-mails par jour. Les différences qui comptent sont ailleurs, et je les ai découvertes en en utilisant plusieurs.
Les en-têtes ajoutés à votre insu. Certains prestataires, pensés d'abord pour le marketing, ajoutent automatiquement un en-tête List-Unsubscribe à tous les envois. Pour une newsletter, c'est une bonne pratique. Pour un code de connexion, c'est un piège : certaines messageries affichent alors un bandeau « liste de diffusion » avec un bouton de désabonnement bien visible. Si l'utilisateur clique dessus, le prestataire inscrit son adresse sur une liste de blocage — et les e-mails suivants, y compris ses codes de connexion, sont jetés sans erreur visible côté application. Avant de choisir, j'envoie désormais un message de test et j'inspecte ses en-têtes bruts.
Le suivi des ouvertures et des clics. Beaucoup de prestataires l'activent par défaut : un pixel invisible dans chaque message, et chaque lien réécrit pour passer par leurs serveurs. Pour un e-mail transactionnel, c'est inutile, discutable du point de vue de la vie privée, et un lien de vérification réécrit vers un domaine tiers peut paraître suspect. Je le désactive systématiquement — et je vérifie qu'il l'est vraiment.
La localisation des données. Un e-mail transactionnel contient au minimum une adresse et souvent un nom : ce sont des données personnelles. Pour des projets européens, un prestataire dont les données restent dans l'Union simplifie considérablement la conformité au RGPD.
Les limites des offres gratuites. Au-delà du volume d'envoi, le nombre de domaines vérifiables est souvent plafonné — parfois à trois. Quand on gère plusieurs projets, c'est ce plafond qu'on atteint en premier, bien avant celui des volumes.
Des clés d'accès restreintes. Je crée une clé par application, limitée à l'envoi depuis son seul domaine, et je garde la clé d'administration du compte hors de toute application. Si une clé fuit, elle ne permet d'envoyer qu'au nom d'un projet, et ne donne accès à rien d'autre.
Pouvoir changer de prestataire en une variable
Un prestataire peut changer ses conditions, suspendre un domaine après une vérification automatique, ou simplement cesser de convenir. La question n'est pas de savoir si on en changera un jour, mais combien ça coûtera. Sur mes projets Node.js, la réponse est : une variable d'environnement.
Plutôt que d'intégrer le SDK propriétaire d'un prestataire, l'application parle SMTP, le protocole standard que tous proposent. Toute la configuration tient dans une URL :
import nodemailer from 'nodemailer'
// prod : smtps://utilisateur:cle@smtp.prestataire.eu:465
// preprod : smtp://mailpit:1025 (boîte de test, rien ne part)
// tests : absente → messages gardés en mémoire
const transport = nodemailer.createTransport(process.env.MAIL_SMTP_URL)Changer de prestataire revient à vérifier le domaine chez le nouveau, publier ses enregistrements DNS, puis modifier cette URL. Sur Wikomplete, c'est exactement ainsi que s'est fait le passage d'un prestataire à un autre : aucune ligne de code modifiée.
Le même mécanisme règle la question des environnements. En préproduction, l'URL pointe vers une boîte de capture qui intercepte tous les messages et les affiche dans une interface web : on peut tester chaque parcours sans jamais risquer d'écrire à un vrai utilisateur. Dans les tests automatisés, les messages sont conservés en mémoire, ce qui permet de récupérer le lien de vérification envoyé et de poursuivre le parcours jusqu'au bout.
Un échec d'envoi ne doit jamais être silencieux
Dernier point, et pas le moindre : l'application doit savoir quand un envoi échoue. La pire expérience possible, c'est un écran « un e-mail vous a été envoyé » alors que rien n'est parti. L'utilisateur attend, vérifie ses spams, réessaie, puis abandonne.
Deux approches, selon le contexte. Quand l'envoi fait partie d'un parcours synchrone — inscription, mot de passe oublié —, un échec lève une erreur que le parcours affiche : mieux vaut dire « l'envoi a échoué, réessayez » que mentir. Quand l'envoi part en tâche de fond pour ne pas ralentir l'utilisateur, chaque message est journalisé en base avec son statut, et une surveillance lit ce journal pour m'alerter dès qu'un envoi échoue. Dans les deux cas, l'échec est connu immédiatement — par l'utilisateur ou par moi —, et non découvert des jours plus tard.
Quelques détails de forme complètent le tout : une version texte en plus de la version HTML, un gabarit sobre sans images lourdes, et le lien d'action écrit en clair sous le bouton, pour les messageries qui bloquent les boutons.
Ce que j'en retiens
La délivrabilité n'a rien de mystérieux. C'est un empilement de précautions simples : un sous-domaine dédié, trois enregistrements DNS correctement alignés, un prestataire dont on a lu les en-têtes et pas seulement la grille tarifaire, une application qui parle un protocole standard, et des échecs qui se voient.
Prises une par une, ces précautions semblent secondaires. Ensemble, elles font la différence entre un utilisateur qui se connecte en dix secondes et un utilisateur qui abandonne votre produit parce que son code n'est jamais arrivé.