Votre site WordPress indique « Message envoyé ». Votre application journalise « Email mis en file ». Les clients jurent qu’ils n’ont rien reçu.
Le marketing vous relance toutes les 30 minutes. Vous vérifiez les dossiers spam. Rien. Vous renvoyez. Toujours rien.
C’est le pire type d’échec : silencieux, nuisible pour la réputation, et suffisamment plausible pour que tout le monde suppose que « ça va probablement ».
Rendons cela inacceptable. Rendons-le ennuyeux. L’ennui est une bonne chose pour la délivrabilité des e-mails.
Ce qui casse réellement quand les e-mails WordPress/app « n’envoient pas »
Quand quelqu’un dit « l’e-mail n’est pas envoyé », il signifie généralement l’un des quatre échecs différents suivants :
1) L’application ne remet jamais le courrier à quelque chose de réel
Problème classique WordPress/PHP : mail() renvoie le succès parce qu’il a remis le contenu à une interface MTA locale,
pas parce que le message a quitté le bâtiment. S’il n’y a pas de MTA local, ou s’il est mal configuré, vous avez l’illusion du succès.
C’est pourquoi « ça marche sur mon portable » n’est pas une stratégie d’e-mail.
2) Le message quitte votre hôte mais meurt au prochain saut
Causes courantes : le port 25 est bloqué par l’hébergeur ; le SMTP sortant est refusé par un pare-feu ; ou votre MTA tente une livraison directe
et est soumis à des limites de débit, au greylisting, ou rejeté avec un code de politique. Le mail peut rester en file pendant des heures, puis rebondir,
ou il peut être accepté puis filtré plus tard. Ce qui mène à…
3) Le destinataire l’accepte, puis les filtres anti-spam l’enterrent
C’est l’échec « livré mais pas vu ». C’est aussi le plus politiquement gênant : votre système dit « envoyé »,
le serveur récepteur dit « accepté », et l’utilisateur dit « non ». Les trois peuvent être vrais.
Absence d’alignement SPF/DKIM/DMARC, mauvaise réputation, rDNS cassé, et domaines « From » que vous ne contrôlez pas sont les principaux coupables.
4) Vous envoyez du trafic légitime qui ressemble à du trafic illégitime
Les e-mails transactionnels (réinitialisations de mot de passe, reçus, formulaires de contact) ont un patron : pics d’envoi lors d’événements, modèles identiques,
objets similaires et liens récurrents. Cela peut paraître spammy si vous n’authentifiez pas ou si l’IP de votre relais est « nouvelle ».
La délivrabilité n’est pas une question de moralité. C’est du matching de patron + réputation.
La solution n’est pas « essayer un autre plugin ». La solution consiste à établir un chemin relais SMTP correct avec authentification,
identité cohérente, alignement DNS et journaux que vous pouvez consulter depuis vos propres systèmes.
Faits intéressants et bref historique (pour comprendre les pannes d’aujourd’hui)
- SMTP est antérieur au web. Il a été standardisé au début des années 1980 et suppose encore un réseau majoritairement de confiance.
- Le port 25 était « le tuyau mail d’Internet ». Aujourd’hui il est souvent bloqué pour les serveurs clients car des hôtes compromis inondent le réseau de spam.
- SPF vient de « stopper les expéditeurs d’enveloppe forgés ». Il vérifie qui peut envoyer des mails pour un domaine via DNS, mais ne couvre qu’une couche d’identité.
- DKIM a été conçu pour survivre au forwarding. Il signe le contenu du message pour que le destinataire puisse vérifier qu’il n’a pas été altéré en transit (ou par une passerelle « utile »).
- DMARC est politique et alignement, pas une magie. Il indique aux récepteurs quoi faire quand SPF/DKIM échouent et exige que les identifiants correspondent au « From » visible.
- Le greylisting est volontairement casse-pieds. Certains serveurs rejettent temporairement les premières tentatives pour voir si vous réessayez comme un vrai MTA. Les apps qui « envoient et oublient » perdent.
- « Accepté » n’est pas égal à « dans la boîte de réception ». L’acceptation SMTP signifie « nous prenons la responsabilité », pas « nous l’avons montré en évidence à un humain ».
- Le reverse DNS est toujours un contrôle de crédibilité. Beaucoup de récepteurs se méfient fortement des IP sans rDNS ou avec rDNS non assorti car c’est courant chez les botnets.
- Les gros fournisseurs utilisent du machine learning sur les flux mail. Votre message est jugé par réputation de domaine, réputation IP, engagement et caractéristiques du contenu.
Playbook de diagnostic rapide (vérifications 1/2/3)
Quand un e-mail « n’envoie pas », la vitesse compte. Vous voulez identifier le goulot en quelques minutes, pas après une réunion.
Voici l’ordre de triage que j’utilise en production.
Premier : déterminer si le mail quitte l’hôte de l’application
- Envoyez un seul e-mail de test avec un objet unique.
- Vérifiez les journaux locaux ou la file (Postfix/Exim) sur l’hôte. S’il n’y a ni file ni journaux, l’application ne l’a jamais remis.
- Confirmez que vous ne dépendez pas de PHP
mail()sans MTA derrière.
Second : déterminer si le prochain saut SMTP est joignable et accepte
- Testez la connectivité sortante vers votre relais sur le port 587 (et 465 si nécessaire). Ne supposez pas que le port 25 fonctionne.
- Tentez une session SMTP authentifiée. Si l’auth échoue, vous n’avez pas un « problème de délivrabilité », mais un « problème d’identifiant ».
- Cherchez des rejets immédiats avec codes SMTP clairs (5xx) versus des reports (4xx).
Troisième : déterminer si le message est rejeté plus tard (politique, réputation, authentification)
- Inspectez les en-têtes d’un message qui arrive quelque part (même dans une boîte de test) pour les résultats SPF/DKIM/DMARC.
- Confirmez l’alignement du domaine From et que vous n’envoyez pas d’un domaine que vous ne contrôlez pas.
- Vérifiez si les rebonds vont quelque part que vous ne surveillez jamais (classique : adresse de rebond VERP qui ne pointe nulle part).
L’objectif de ce playbook est de classer la panne en : remise application, réseau/auth, ou politique de délivrabilité.
Chaque catégorie a une correction différente. Les mélanger fait perdre des jours.
L’architecture qui assure la livraison (et pourquoi)
Le modèle fiable est simple : votre application parle en soumission SMTP à un relais, le relais gère la livraison.
Le relais est authentifié, journalisé, soumis à des limites de débit et aligné avec l’identité de votre domaine.
Ce que vous devriez faire (opinion)
- Utiliser la soumission SMTP (587) avec authentification depuis WordPress/app vers un relais.
- Envoyer depuis un domaine que vous contrôlez et configurer correctement les enregistrements DNS (SPF/DKIM/DMARC).
- Centraliser l’envoi pour pouvoir appliquer des politiques et voir les journaux en un point.
- Séparer les flux transactionnels et marketing si les volumes diffèrent ; réputations différentes, modes de défaillance différents.
- Préférer un relais SMTP géré sauf si vous avez une raison de gérer vous-même la réputation sortante.
Ce que vous devriez éviter
- Livraison directe vers les MX depuis des serveurs web aléatoires. Ça marche jusqu’à ce que ça casse, puis vous héritez de la réputation, des limites et des listes de blocage.
- Utiliser « From: votremarque.com » tout en envoyant via « autrechose.com ». Cela casse l’alignement et la confiance.
- Multiplier les plugins/config SMTP sur différents serveurs. Vous vous retrouverez avec 12 variantes subtilement cassées.
Une plaisanterie, pour la route : la délivrabilité des e-mails ressemble aux rencontres — si vous arrivez avec un faux nom et sans références, personne ne rappelle.
Choisir un relais SMTP : ce qui compte et ce qui n’est que du bruit
Vous pouvez exécuter votre propre relais (Postfix), utiliser le relais e-mail de votre cloud, ou acheter un service spécialisé pour e-mails transactionnels.
La « meilleure » réponse dépend de la conformité, du volume, et de votre plaisir à déboguer les scores de réputation comme un hobby.
Ce qui compte
- Options d’authentification : SMTP AUTH sur TLS, idéalement avec des identifiants par application.
- Support DKIM : soit le relais signe, soit vous signez ; mais il faut de la consistance.
- Traitement des rebonds : vous avez besoin de visibilité. Au minimum, une boîte pour les rebonds ; mieux, des journaux d’événements.
- Contrôles de débit : à la fois pour protéger votre réputation et prévenir des inondations accidentelles dûes à une boucle cassée.
- Gestion réputation IP/domaine : qui en est propriétaire, et à quelle vitesse ça se rétablit après un incident.
- Accès aux logs : vous devez avoir les résultats de livraison avec des IDs de message. « Nous l’avons envoyé » n’est pas une preuve.
Ce qui est surtout du bruit
- Promesses d’envoi « illimité » sans plan de réputation.
- Tableaux de bord sophistiqués si vous ne pouvez pas exporter ou corréler les IDs de message.
- « Intégration WordPress en un clic » qui masque l’identité SMTP réelle et casse l’alignement.
Tâches pratiques (commandes, sorties attendues et décisions)
Ces tâches supposent un serveur Linux exécutant Postfix comme MTA local ou relais, plus un hôte WordPress/app qui soumet le mail.
Même si vous utilisez un relais géré, beaucoup de ces vérifications s’appliquent (réseau, TLS, DNS et traçage de message).
Task 1 — Confirmer que Postfix est installé et fonctionne
cr0x@server:~$ systemctl status postfix
● postfix.service - Postfix Mail Transport Agent
Loaded: loaded (/lib/systemd/system/postfix.service; enabled)
Active: active (running) since Mon 2026-01-04 08:11:02 UTC; 2h 13min ago
Docs: man:postfix(1)
Main PID: 1327 (master)
Tasks: 3 (limit: 4567)
Memory: 12.3M
CGroup: /system.slice/postfix.service
├─1327 /usr/lib/postfix/sbin/master -w
├─1331 qmgr -l -t unix -u
└─1332 tlsmgr -l -t unix -u
Ce que cela signifie : S’il n’est pas active (running), votre « relais SMTP » est imaginaire.
Décision : S’il est inactif, démarrez-le et vérifiez la configuration avant de toucher à WordPress.
Task 2 — Vérifier si quelque chose est bloqué dans la file d’envoi
cr0x@server:~$ postqueue -p
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
A1B2C3D4E5 3120 Mon Jan 4 09:22:14 no-reply@example.com
user@gmail.com
(connect to gmail-smtp-in.l.google.com[142.250.102.27]:25: Connection timed out)
Ce que cela signifie : Postfix a accepté le mail mais ne peut pas atteindre le MX distant (timeout). C’est un souci réseau ou le port 25 en sortie.
Décision : Si vous voyez des timeouts, cessez la livraison directe vers les MX et relayezz via soumission (587) vers un fournisseur.
Task 3 — Inspecter les journaux récents pour rejets/retards
cr0x@server:~$ sudo tail -n 50 /var/log/mail.log
Jan 4 10:05:12 server postfix/smtp[24518]: A1B2C3D4E5: to=<user@gmail.com>, relay=gmail-smtp-in.l.google.com[142.250.102.27]:25, delay=67, delays=0.1/0.02/67/0, dsn=4.4.1, status=deferred (connect to gmail-smtp-in.l.google.com[142.250.102.27]:25: Connection timed out)
Jan 4 10:05:45 server postfix/smtpd[24544]: warning: unknown[203.0.113.50]: SASL LOGIN authentication failed: authentication failure
Jan 4 10:05:45 server postfix/smtpd[24544]: disconnect from unknown[203.0.113.50] ehlo=1 auth=0/1 rset=1 quit=1 commands=3/4
Ce que cela signifie : Vous avez deux problèmes distincts : timeouts de livraison sortante (direct-to-MX) et échecs d’authentification entrants (clients mal configurés ou malveillants).
Décision : Verrouillez la soumission et corrigez votre chemin de relais pour ne pas livrer sur le port 25 depuis des nœuds web aléatoires.
Task 4 — Vérifier la connectivité sortante vers le relais prévu (port 587)
cr0x@server:~$ nc -vz smtp.relay.local 587
Connection to smtp.relay.local 587 port [tcp/submission] succeeded!
Ce que cela signifie : Le chemin réseau existe. Si cela échoue, votre pare-feu/groupe de sécurité/DNS est en faute.
Décision : Corrigez le routage/pare-feu avant de modifier la configuration de l’application.
Task 5 — Tester la négociation TLS et les détails du certificat
cr0x@server:~$ openssl s_client -starttls smtp -connect smtp.relay.local:587 -servername smtp.relay.local -brief
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Peer certificate: CN = smtp.relay.local
Verification: OK
Ce que cela signifie : TLS fonctionne et le certificat est valide. Si la vérification échoue, de nombreux clients refuseront d’envoyer.
Décision : Corrigez les certificats (ou le magasin de confiance) au lieu de « désactiver la vérification » dans l’app.
Task 6 — Tenter une session SMTP authentifiée (signal rapide manuel)
cr0x@server:~$ swaks --to user@example.net --from no-reply@example.com --server smtp.relay.local --port 587 --auth LOGIN --auth-user app-smtp --auth-password 'REDACTED' --tls
=== Trying smtp.relay.local:587...
=== Connected to smtp.relay.local.
=== TLS started with cipher TLS_AES_256_GCM_SHA384
<= 220 smtp.relay.local ESMTP Postfix
=> EHLO server
<= 250-smtp.relay.local
<= 250-AUTH PLAIN LOGIN
<= 250 STARTTLS
=> AUTH LOGIN
<= 235 2.7.0 Authentication successful
=> MAIL FROM:<no-reply@example.com>
<= 250 2.1.0 Ok
=> RCPT TO:<user@example.net>
<= 250 2.1.5 Ok
=> DATA
<= 354 End data with <CR><LF>.<CR><LF>
=> .
<= 250 2.0.0 Ok: queued as 9F8E7D6C5B
=== Message sent.
Ce que cela signifie : Vous pouvez soumettre un mail avec succès. L’ID de file est traçable dans les journaux du relais.
Décision : Si cela marche mais que WordPress ne fonctionne pas, votre plugin/config app est mauvais, pas le réseau.
Task 7 — Tracer un ID de message dans les journaux (arrêtez de deviner)
cr0x@server:~$ sudo grep '9F8E7D6C5B' /var/log/mail.log
Jan 4 11:14:22 server postfix/cleanup[27102]: 9F8E7D6C5B: message-id=<20260104111422.9F8E7D6C5B@smtp.relay.local>
Jan 4 11:14:22 server postfix/qmgr[1331]: 9F8E7D6C5B: from=<no-reply@example.com>, size=1023, nrcpt=1 (queue active)
Jan 4 11:14:23 server postfix/smtp[27105]: 9F8E7D6C5B: to=<user@example.net>, relay=mx.example.net[198.51.100.20]:25, delay=1.1, delays=0.1/0.02/0.4/0.6, dsn=2.0.0, status=sent (250 2.0.0 OK)
Ce que cela signifie : La livraison de bout en bout vers le MX du destinataire a réussi.
Décision : Si les utilisateurs ne le voient toujours pas, vous êtes en territoire « filtrage anti-spam ou règles de boîte » — passez à l’analyse des en-têtes et aux vérifications d’authentification.
Task 8 — Confirmer que le nom d’hôte et le FQDN du serveur sont cohérents
cr0x@server:~$ hostnamectl
Static hostname: smtp.relay.local
Icon name: computer-vm
Chassis: vm
Machine ID: 2b3f4c5d6e7f8a9b
Boot ID: 0a1b2c3d4e5f6a7b
Operating System: Ubuntu 22.04.4 LTS
Kernel: Linux 5.15.0-91-generic
Architecture: x86-64
Ce que cela signifie : Un nom d’hôte cohérent aide à éviter des incohérences HELO/EHLO.
Décision : Si votre nom d’hôte est localhost ou change, corrigez-le et mettez à jour myhostname dans Postfix.
Task 9 — Vérifier le DNS pour SPF (et interpréter le résultat)
cr0x@server:~$ dig +short TXT example.com
"v=spf1 include:_spf.relayvendor.net -all"
Ce que cela signifie : SPF est présent et strict (-all). Bien — si c’est correct.
Décision : Si vous n’envoyez pas réellement via _spf.relayvendor.net, corrigez SPF ou vos mails échoueront aux vérifications SPF.
Task 10 — Vérifier la publication de la clé DKIM (sélecteur)
cr0x@server:~$ dig +short TXT s1._domainkey.example.com
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
Ce que cela signifie : La clé publique DKIM existe pour le sélecteur s1.
Décision : Si elle manque, la signature DKIM peut encore exister mais ne validera pas ; publiez la clé correcte ou configurez le relais pour signer.
Task 11 — Vérifier la politique DMARC et les adresses de rapport
cr0x@server:~$ dig +short TXT _dmarc.example.com
"v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensics@example.com; adkim=s; aspf=s"
Ce que cela signifie : DMARC applique la mise en quarantaine et un alignement strict.
Décision : Si vous êtes en train d’intégrer un relais, envisagez p=none temporairement pendant que vous validez l’alignement — puis appliquez.
Task 12 — Vérifier le reverse DNS pour votre IP sortante
cr0x@server:~$ dig +short -x 198.51.100.10
smtp.example.com.
Ce que cela signifie : Le rDNS existe. S’il pointe vers quelque chose de générique ou manque, certains récepteurs vous méfieront.
Décision : Si vous gérez vos propres IPs, définissez le rDNS sur un nom d’hôte stable qui correspond raisonnablement au DNS direct.
Task 13 — Vérifier si le port 25 en sortie est bloqué (réalité direct-to-MX)
cr0x@server:~$ nc -vz gmail-smtp-in.l.google.com 25
nc: connect to gmail-smtp-in.l.google.com (142.250.102.27) port 25 (tcp) failed: Connection timed out
Ce que cela signifie : Vous ne pouvez pas livrer directement à Gmail sur le port 25 depuis cet hôte (bloqué ou filtré).
Décision : Utilisez un relais de soumission sur 587. Ne combattez pas la politique d’egress de votre fournisseur avec des « astuces ».
Task 14 — Confirmer que l’hôte WordPress n’essaie pas d’exécuter « sendmail » sans MTA
cr0x@server:~$ command -v sendmail || echo "sendmail not found"
sendmail not found
Ce que cela signifie : PHP mail() échouera probablement ou sera silencieusement inopérant selon la configuration.
Décision : Configurez WordPress pour utiliser explicitement la soumission SMTP ; ne dépendez pas d’un binaire local manquant.
Task 15 — Surveiller les logs en direct lors de l’envoi d’un test (vérité en temps réel)
cr0x@server:~$ sudo tail -f /var/log/mail.log
Jan 4 11:29:17 server postfix/smtpd[28110]: connect from web01[203.0.113.11]
Jan 4 11:29:18 server postfix/smtpd[28110]: 1A2B3C4D5E: client=web01[203.0.113.11], sasl_method=LOGIN, sasl_username=app-smtp
Jan 4 11:29:18 server postfix/cleanup[28113]: 1A2B3C4D5E: message-id=<6f9d2a3c9e1b@web01>
Jan 4 11:29:18 server postfix/qmgr[1331]: 1A2B3C4D5E: from=<no-reply@example.com>, size=1845, nrcpt=1 (queue active)
Jan 4 11:29:19 server postfix/smtp[28115]: 1A2B3C4D5E: to=<user@example.net>, relay=mx.example.net[198.51.100.20]:25, delay=1.2, dsn=2.0.0, status=sent (250 2.0.0 OK)
Ce que cela signifie : Vous voyez le client se connecter, s’authentifier, mettre en file et livrer. C’est toute l’histoire.
Décision : Si la connexion n’apparaît jamais, WordPress n’utilise pas votre relais. Corrigez les paramètres du plugin et les identifiants.
Task 16 — Valider la configuration Postfix pour les pièges évidents
cr0x@server:~$ sudo postconf -n
myhostname = smtp.relay.local
mydestination = $myhostname, localhost.localdomain, localhost
inet_interfaces = all
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,reject_unauth_destination
Ce que cela signifie : Lignes clés : SASL auth activé, et reject_unauth_destination empêche l’open relay.
Décision : Si vous ne voyez pas reject_unauth_destination, arrêtez-vous et corrigez avant d’exposer ce serveur sur le réseau.
Deuxième plaisanterie (et dernière) : un open relay, c’est comme laisser votre voiture déverrouillée avec les clés à l’intérieur — sauf que les amendes arrivent chez votre patron.
Configuration Postfix de qualité production (avec garde-fous)
Il y a deux rôles de « relais » que les gens confondent :
(1) un serveur de soumission qui accepte le mail authentifié de vos apps,
et (2) un smart host qui relaie le mail sortant via un fournisseur en amont.
Vous pouvez exécuter les deux rôles sur une instance Postfix, mais soyez explicite.
Pattern A : serveur de soumission Postfix qui relaie vers un provider géré
C’est ce que je recommande pour la plupart des équipes : les apps soumettent à votre Postfix sur 587 avec SMTP AUTH, Postfix transmet au provider sur 587.
Vous obtenez des journaux centralisés et des politiques, et vous ne gérez pas la réputation IP.
Installer les paquets (exemple Debian/Ubuntu)
cr0x@server:~$ sudo apt-get update
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Reading package lists... Done
cr0x@server:~$ sudo apt-get install -y postfix libsasl2-modules mailutils
Reading package lists... Done
Building dependency tree... Done
Setting up postfix (3.6.4-1ubuntu1.3) ...
Décision : Si vous êtes dans un environnement qui a déjà Exim ou un autre MTA, ne superposez pas les MTA. Choisissez-en un.
Configurer Postfix pour la soumission authentifiée et le relais sûr
Éditez /etc/postfix/main.cf (montrant l’essentiel, pas tous les défauts). Les valeurs sont des exemples ; ajustez noms d’hôtes/domaines.
cr0x@server:~$ sudo postconf -e "myhostname = smtp.example.com"
cr0x@server:~$ sudo postconf -e "myorigin = example.com"
cr0x@server:~$ sudo postconf -e "mydestination = \$myhostname, localhost.localdomain, localhost"
cr0x@server:~$ sudo postconf -e "inet_interfaces = all"
cr0x@server:~$ sudo postconf -e "mynetworks = 127.0.0.0/8 [::1]/128"
cr0x@server:~$ sudo postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated, reject_unauth_destination"
cr0x@server:~$ sudo postconf -e "smtpd_sasl_auth_enable = yes"
cr0x@server:~$ sudo postconf -e "smtpd_tls_security_level = may"
cr0x@server:~$ sudo postconf -e "smtpd_tls_auth_only = yes"
cr0x@server:~$ sudo postconf -e "smtp_tls_security_level = may"
Ce que cela fait :
Le serveur n’est pas un open relay ; seuls les utilisateurs authentifiés peuvent relayer.
TLS est utilisé pour l’auth (pour ne pas transmettre les mots de passe en clair).
Activer le service submission sur le port 587
Dans /etc/postfix/master.cf, assurez-vous que submission est activé et exige le chiffrement.
Vous pouvez le faire par un ajout sûr + révision manuelle. Après édition, vérifiez avec postfix check.
cr0x@server:~$ sudo grep -n '^submission' -A6 /etc/postfix/master.cf
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
Décision : Si vous ne pouvez pas appliquer TLS sur la submission, ne lancez pas la submission sur un segment réseau non fiable.
Configurer Postfix pour relayer en sortie via un smart host en amont
Si votre fournisseur vous donne smtp.provider.tld:587 avec des identifiants, définissez relayhost et la map de mots de passe SASL.
cr0x@server:~$ sudo postconf -e "relayhost = [smtp.provider.tld]:587"
cr0x@server:~$ sudo postconf -e "smtp_sasl_auth_enable = yes"
cr0x@server:~$ sudo postconf -e "smtp_sasl_security_options = noanonymous"
cr0x@server:~$ sudo postconf -e "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd"
cr0x@server:~$ sudo postconf -e "smtp_tls_security_level = encrypt"
cr0x@server:~$ sudo bash -c 'cat > /etc/postfix/sasl_passwd <<EOF
[smtp.provider.tld]:587 relay-user:relay-password
EOF'
cr0x@server:~$ sudo postmap /etc/postfix/sasl_passwd
cr0x@server:~$ sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
Décision : Si vous mettez /etc/postfix/sasl_passwd dans Git, arrêtez. Mettez les identifiants dans un coffre de secrets et générez-les au déploiement.
Redémarrer et valider la configuration
cr0x@server:~$ sudo postfix check
cr0x@server:~$ sudo systemctl restart postfix
cr0x@server:~$ sudo systemctl is-active postfix
active
Ce que cela signifie : Postfix a accepté la config et tourne.
Décision : Si postfix check se plaint, corrigez ça d’abord ; ne « redémarrez pas jusqu’à ce que ça marche ».
Bases du durcissement à ne pas sauter
- Pare-feu : n’exposez le 587 qu’aux réseaux d’application/VPN, et le 25 seulement si vous en avez vraiment besoin (beaucoup n’en ont pas).
- Limitation de débit : bridez par client pour éviter qu’un WordPress compromis n’envoie 200k « factures ».
- Ségrégation des identifiants : identifiants SMTP différents par environnement (prod/stage/dev) et par app si possible.
- Rétention des journaux : conservez assez pour enquêter sur les litiges ; mais ne journalisez pas les corps de message sauf si la politique le permet.
Une citation d’ingénierie pour rester honnête : « L’espoir n’est pas une stratégie. » — idée paraphrasée attribuée à la culture opérationnelle (répétée dans les équipes SRE).
Authentification DNS qui impacte la délivrabilité (SPF, DKIM, DMARC, rDNS)
La livraison du mail, c’est moitié SMTP moitié identité. Il vous faut les deux.
L’authentification n’assure pas la placement en boîte, mais son absence garantit des ennuis.
SPF : qui est autorisé à envoyer
SPF vérifie l’expéditeur d’enveloppe (Return-Path / MAIL FROM). Les récepteurs interrogent DNS pour un enregistrement TXT du domaine.
Si vous envoyez via un fournisseur relais, votre SPF doit les inclure.
À faire : publiez un seul enregistrement SPF, gardez-le sous les limites de requêtes DNS (réalité pratique),
et utilisez -all quand vous êtes confiant.
À éviter : plusieurs enregistrements SPF (les récepteurs le traitent comme permerror), et « mettre +all » (ce qui annule l’intérêt).
DKIM : signature du contenu
DKIM signe les en-têtes et le corps ; les récepteurs valident avec la clé publique en DNS.
C’est sensible aux modifications du message — certaines passerelles « sécurité » ou ajouts de pied-de-page peuvent casser DKIM.
À faire : qu’un seul composant signe (votre relais ou le provider), faites tourner les clés, et gardez des sélecteurs stables par flux d’envoi.
DMARC : politique + alignement
DMARC ajoute deux idées cruciales :
(1) dire aux récepteurs quoi faire en cas d’échec d’authentification, et
(2) exiger l’alignement entre le domaine visible dans le header From et les domaines authentifiés par SPF/DKIM.
Déploiement recommandé : commencez par p=none pour observer, puis passez à quarantine, puis à reject.
Si votre org a plusieurs expéditeurs (helpdesk, CRM, marketing), faites l’inventaire d’abord sinon vous brisez du mail légitime.
Reverse DNS (rDNS) : l’identité de l’IP
Si vous gérez l’IP sortante, configurez le rDNS. Si vous utilisez un fournisseur, il s’en occupe généralement.
Les récepteurs utilisent le rDNS comme indice de crédibilité. Pas strictement requis partout, mais l’absence de rDNS ressemble à arriver à un entretien sans pièce d’identité.
Vérification d’alignement : « From » doit être à vous
La blessure la plus courante auto-infligée : WordPress envoie « From: wordpress@nom-hote » ou « From: info@gmail.com »
tandis que l’expéditeur d’enveloppe est tout autre. DMARC voit le désalignement et les récepteurs vous traitent comme suspect.
Corrigez le domaine From. Possédez-le.
Schémas de configuration WordPress/app qui ne vous sabotent pas
WordPress lui-même n’est pas le méchant ; c’est la configuration incohérente qui l’est.
Votre travail est de faire en sorte que WordPress se comporte comme un client bien élevé : soumission SMTP authentifiée, identité stable, en-têtes sensés.
Choisissez un seul chemin d’envoi et imposez-le
Si vous exécutez une soumission Postfix en interne, tout doit soumettre vers elle. Si vous utilisez un relais géré directement depuis WordPress,
faites-le de façon cohérente. Ce que vous ne voulez pas :
- certains e-mails passant par PHP
mail(), - d’autres passant par le plugin SMTP A,
- et les réinitialisations de mot de passe par le plugin B parce qu’il « a réparé » un truc l’année dernière.
Utilisez une adresse expéditeur dédiée pour les mails transactionnels
Utilisez quelque chose comme no-reply@votredomaine ou notifications@votredomaine.
Restez cohérent. Les récepteurs apprennent des patrons. Les humains aussi.
Définissez Reply-To intentionnellement
Si les utilisateurs doivent répondre, configurez Reply-To vers une adresse surveillée. S’ils ne doivent pas, envisagez quand même une boîte surveillée pour les rebonds.
Les échecs silencieux se cachent souvent dans des rebonds que vous ne lisez jamais.
N’envoyez pas au nom d’un domaine que vous ne contrôlez pas
Envoyer « From: votremarque@gmail.com » depuis votre serveur est du sabotage de délivrabilité. Cela complique aussi l’audit.
Utilisez votre domaine, authentifiez-le, et orientez les réponses où vous le souhaitez.
Applications : privilégiez les bibliothèques SMTP avec gestion d’erreurs explicite
Que ce soit PHP, Node, Python ou Java : configurez votre client SMTP pour échouer bruyamment et journaliser les réponses SMTP.
Si votre app engloutit les exceptions, vous apprendrez les échecs d’e-mail par des clients en colère. Ce n’est pas un bon système de supervision.
Surveillance, alertes et preuves : arrêter les suppositions
Un e-mail fiable n’est pas « configurer et oublier ». C’est configurer, observer et appliquer.
Vous avez besoin d’au moins trois couches : santé du service, santé de la file, et signaux de délivrabilité.
Santé du service
- Alerter si Postfix est arrêté.
- Alerter si le disque est presque plein (les files et journaux ont besoin d’espace ; disque plein = erreurs créatives).
- Alerter sur l’expiration des certificats TLS si vous terminez TLS vous-même.
Santé de la file
Une file de mail qui grossit n’est pas un « bruit de fond normal ». C’est un symptôme visible de rejet en amont, problème réseau,
échec d’identifiants, ou throttling.
cr0x@server:~$ postqueue -p | tail -n 5
-- 2 Kbytes in 1 Request.
Décision : Si c’est constamment non nul et en augmentation, alertez et investigatez les codes de réponse SMTP dans les journaux.
Signaux de délivrabilité
Au minimum : conservez des échantillons d’en-têtes livrés et vérifiez que SPF/DKIM/DMARC passent régulièrement.
Mieux : collectez les codes de rebond et catégorisez-les (auth, politique, boîte pleine, rejet spam).
Corrélation sur les IDs de message
Votre relais doit journaliser les IDs de file et les IDs en amont. Votre application doit journaliser un ID de corrélation pour « intention e-mail ».
Si vous ne pouvez pas tracer « utilisateur a cliqué réinitialiser → message accepté par le relais → livré ou rebondi »,
vous n’avez pas un système e-mail. Vous avez des impressions.
Trois mini-récits d’entreprise du terrain
Mini-récit 1 : l’incident causé par une mauvaise hypothèse
Une entreprise SaaS de taille moyenne utilisait WordPress pour les pages marketing et une app personnalisée pour le produit.
Les réinitialisations de mot de passe étaient « envoyées » (selon les logs de l’app). Les formulaires de contact étaient « envoyés » (selon WordPress).
Les tickets de support ont explosé : les utilisateurs ne pouvaient pas se connecter.
L’hypothèse erronée était subtile : tout le monde croyait qu’un appel API réussi au mailer de l’application voulait dire une livraison réussie.
En réalité, l’app était configurée pour utiliser l’interface locale sendmail, qui remettait simplement les messages dans une file locale. Cette file existait — à peine.
L’image VM avait un MTA installé des mois plus tôt, mais personne ne s’en occupait. Personne ne le surveillait. Personne ne lisait les logs mail.
Lors d’un cycle de patch OS, l’hôte a redémarré et est revenu avec un nom d’hôte changé et une configuration de résolveur manquante (cloud-init « a aidé »).
Postfix a démarré, mais ne pouvait pas résoudre les MX distants. Les messages se sont mis en file et en file. L’app continuait à renvoyer succès.
Pendant ce temps, quelques messages ont percé après la récupération du DNS, arrivant des heures plus tard et embrouillant encore plus.
La correction n’était pas héroïque. Ils sont passés à la soumission SMTP vers un relais unique, ont journalisé les IDs de file dans l’app,
et ont mis une alerte pour file > petit seuil pendant plus de quelques minutes.
La fois suivante qu’un incident DNS est survenu, ils l’ont vu immédiatement. Plus de devinettes. Plus d’archéologie client.
Mini-récit 2 : l’optimisation qui a mal tourné
Une autre société a décidé que leur fournisseur d’e-mails transactionnels était « trop cher ».
Ils avaient un beau cluster Kubernetes, une équipe SRE compétente, et juste assez de confiance pour être dangereux.
Le plan : envoyer le mail directement depuis les pods d’app en utilisant une bibliothèque SMTP légère vers les MX des destinataires.
Sur le papier, ça paraissait efficace : moins de dépendances, pas d’enfermement fournisseur, et « SMTP c’est juste un protocole ».
En réalité, ils ont redécouvert pourquoi l’e-mail sortant est un service spécialisé.
Leur fournisseur cloud bloquait le port 25 depuis les nœuds. Ils ont demandé une exception et l’ont obtenue — en partie.
Certains chemins d’egress fonctionnaient ; d’autres étaient silencieusement limités. La livraison est devenue non déterministe selon les pods.
Puis la réputation est entrée en jeu. Leurs IPs sortantes changeaient au fil de la rotation des nœuds.
La signature DKIM était incohérente parce que différentes déploiements avaient des secrets légèrement différents.
Certains messages passaient, d’autres échouaient. L’alignement DMARC était instable. Les récepteurs ont commencé à limiter et mettre en spam.
L’« optimisation » n’a pas seulement coûté du temps ; elle a entraîné une méfiance envers leur domaine.
Ils ont reculé. La solution ennuyeuse : relais centralisé avec identité stable, DKIM cohérent, et un provider qui gère réellement la réputation.
L’équipe SRE n’a pas perdu la face ; elle a tiré une leçon opérationnelle : le mail le moins coûteux est celui que vous n’avez pas à expliquer.
Mini-récit 3 : la pratique ennuyeuse mais correcte qui a sauvé la journée
Une grande entreprise avait une habitude que je respecte vraiment : chaque e-mail transactionnel avait un trace ID dans un en-tête,
et chaque saut SMTP le journalisait. Pas « parfois ». À chaque fois.
C’était appliqué en CI : si votre mailer n’ajoutait pas l’en-tête, le build échouait.
Un matin, la finance a signalé des e-mails de facture manquants. Les ventes ont escaladé. La tempête habituelle a commencé :
« L’app est-elle en panne ? » « Est-ce le réseau ? » « Quelqu’un a-t-il changé le DNS ? » Les gens ont commencé à composer des théories comme c’était un projet de groupe.
Au lieu de cela, l’astreint a extrait un trace ID des logs de l’app, l’a cherché dans les logs du relais, et a trouvé une acceptance SMTP 250 propre du relais,
suivie de deferrals 4xx répétés depuis le fournisseur en amont : throttling temporaire de politique.
La file grossissait, mais dans des limites configurées. Les retries avaient lieu. Rien n’était « cassé », c’était lent.
Parce qu’ils avaient des preuves, ils ont fait la seule chose sensée : informer les parties prenantes du retard, réduire temporairement le taux de rafale,
et laisser la file se vider. Pas de panique, pas de bidouillage de config.
Pratique ennuyeuse, journée ennuyeuse. C’est le rêve.
Erreurs courantes : symptôme → cause → correction
« WordPress dit envoyé, mais rien n’arrive » → PHP mail() remet localement → utiliser la soumission SMTP
Symptôme : Le plugin WordPress rapporte succès ; pas de rebonds ; pas de logs mail.
Cause : PHP mail() ne garantit pas la livraison ; MTA local manquant ou cassé.
Correction : Configurez WordPress pour utiliser SMTP (587) vers votre relais ; vérifiez avec des logs relais en direct et un test comme swaks.
« Le mail reste en file des heures » → direct-to-MX bloqué ou différé → relayer via provider sur 587
Symptôme : postqueue -p montre beaucoup de messages différés ; les logs indiquent des timeouts vers le port 25.
Cause : port 25 sortant bloqué ; greylisting sans retries ; filtrage réseau.
Correction : routez via un smart host en amont sur 587 avec auth ; gardez la logique de retry dans Postfix, pas dans l’app.
« Gmail accepte mais messages en spam » → authentification/alignement faible → corriger SPF/DKIM/DMARC
Symptôme : messages dans spam ; en-têtes montrent SPF softfail/neutral ou DKIM fail ; DMARC fail.
Cause : domaine d’envoi non aligné ; DKIM manquant ; SPF pointant vers de mauvais expéditeurs.
Correction : alignez le domaine From avec les domaines authentifiés ; publiez les includes SPF, activez la signature DKIM, déployez DMARC après validation.
« Certains e-mails partent, d’autres non » → chemins d’envoi multiples → imposer une seule route
Symptôme : réinitialisation fonctionne ; formulaire de contact non ; ou inverse.
Cause : différents plugins/fonctions utilisent des MTA différents ou des identifiants différents.
Correction : standardisez : tout le mail via un point de soumission SMTP ; désactivez les plugins legacy et les chemins mail locaux.
« Auth échouée » → mauvais identifiants ou mismatch TLS → corriger SMTP AUTH et validation cert
Symptôme : logs montrent des échecs SASL ; l’app indique « Could not authenticate. »
Cause : mauvais user/password ; usage du port 25 sans soumission ; TLS requis mais non utilisé.
Correction : confirmez avec swaks ; imposez TLS sur 587 ; faites tourner les identifiants et utilisez des secrets par app.
« Les rebonds n’apparaissent jamais » → Return-Path pointant nulle part → configurer le traitement des rebonds
Symptôme : les utilisateurs signalent des non-livraisons ; vous n’avez pas de boîte à rebonds.
Cause : expéditeur d’enveloppe non surveillé ; le relais réécrit le Return-Path ; ou vous n’avez jamais configuré un domaine de rebond.
Correction : assurez-vous que les rebonds vont vers une boîte ou un système surveillé ; journalisez et catégorisez les DSN.
« Après activation DMARC reject, le mail légitime casse » → expéditeurs oubliés → inventaire d’abord
Symptôme : le helpdesk/CRM/anciens systèmes voient leur mail disparaître.
Cause : enforcement DMARC sans cartographier toutes les sources ; pas de signature DKIM sur certains systèmes.
Correction : commencez DMARC avec p=none, examinez les rapports, puis appliquez ; migrez les expéditeurs dispersés vers le relais ou signez correctement.
Listes de contrôle / plan pas à pas
Plan A (recommandé) : WordPress/app → Postfix submission → provider relais géré
- Choisir votre domaine expéditeur pour les mails transactionnels (exemple :
example.com). - Mettre en place un endpoint de soumission (Postfix sur 587) accessible uniquement depuis vos serveurs d’app.
- Configurer le relayhost en amont dans Postfix vers votre provider sur 587 avec SMTP AUTH.
- Configurer WordPress/app pour utiliser SMTP vers votre hôte de soumission Postfix avec TLS et identifiants par app.
- Publier SPF pour le domaine en incluant le provider (et seulement ce que vous utilisez réellement).
- Activer la signature DKIM (provider ou relais) et publier les clés du sélecteur.
- Déployer DMARC en p=none initialement ; confirmer l’alignement ; puis passer à quarantine/reject.
- Configurer le traitement des rebonds (Return-Path) et surveiller les DSN.
- Ajouter la surveillance : service postfix, taille de file, alertes basées sur les logs pour 4xx/5xx répétés.
- Exécuter une matrice de tests : envoyer vers quelques gros providers ; inspecter les en-têtes ; confirmer les passes.
Checklist d’urgence « faire envoyer maintenant » (sans créer de dette future)
- Cessez d’utiliser la livraison directe vers les MX depuis les serveurs web si le port 25 est instable.
- Faites fonctionner la soumission SMTP avec
swaksd’abord ; puis pointez WordPress/app dessus. - Utilisez une adresse From sur votre domaine (pas un domaine gratuit).
- Publiez SPF et DKIM avant de commencer les envois massifs.
- Activez la journalisation et conservez les IDs de message.
« Nous voulons gérer notre propre livraison sortante » checklist (la taxe réalité)
- Confirmez que l’egress port 25 est autorisé et stable sur tous les chemins de sortie.
- Configurer rDNS et DNS direct ; maintenir des IPs stables.
- Implémentez la signature DKIM et la rotation des clés.
- Implémentez le traitement des feedback loops quand disponible (plaintes et rebonds).
- Chauffer les IPs et domaines (montée progressive du trafic).
- Construire la surveillance pour événements de listes de blocage et patterns de rejet.
Si cette liste vous semble être un second travail, c’est parce que c’en est un.
FAQ (les questions qu’on se pose à 2 h du matin)
1) Pourquoi WordPress indique-t-il « envoyé » quand rien n’arrive ?
Parce que beaucoup de chemins ne confirment qu’une remise locale (à l’interface mail de PHP ou à un MTA local),
pas la livraison finale. « Envoyé » signifie souvent « je l’ai déposé dans un tuyau ».
2) Dois-je utiliser le port SMTP 25, 465 ou 587 ?
Utilisez 587 pour la soumission client avec authentification et TLS. Le port 25 est pour serveur à serveur et souvent bloqué pour les clients.
Le port 465 est l’héritage « TLS implicite » et est encore utilisé, mais 587 est la norme moderne.
3) Puis-je juste utiliser SMTP Gmail pour mon site ?
Vous pouvez pour petit volume, mais ce n’est généralement pas adapté à long terme : limites de débit, gestion d’identifiants, et problèmes d’alignement.
De plus, dépendre d’une boîte personnelle pour la production vous conduit à déboguer l’e-mail depuis un lounge d’aéroport.
4) Quelle est la configuration DNS minimale pour la délivrabilité ?
SPF et DKIM au minimum, avec DMARC ajouté rapidement. Si vous exploitez vos propres IPs d’envoi, ajoutez le rDNS.
Sans ça, vous pariez contre le scepticisme par défaut des récepteurs.
5) Qu’est-ce que l’alignement DMARC veut dire réellement ?
Ça veut dire que le domaine visible dans le header From: doit correspondre (ou être un parent selon la stricte) aux domaines authentifiés par SPF et/ou DKIM.
Le désalignement est une cause fréquente pour laquelle du mail légitime finit en spam.
6) Pourquoi vois-je des messages « deferred » dans la file ?
Les deferrals sont des échecs temporaires (4xx). Causes : greylisting, limites de débit, blocages politiques temporaires, ou problèmes réseau.
Les deferrals ne sont pas « acceptables » s’ils s’accumulent ; ils le sont seulement s’ils se réessayent et se vident de façon prévisible.
7) Comment prouver qu’un e-mail a été livré ?
Vous pouvez prouver que votre serveur SMTP a reçu un 250 « sent/accepted » du MX destinataire.
Vous ne pouvez pas prouver qu’un humain l’a lu. Si vous avez besoin d’une preuve de lecture humaine, c’est un problème produit (notifications in-app, reçus, etc.).
8) Mon serveur WordPress doit-il exécuter Postfix directement ?
Parfois. Mais il est généralement préférable de garder WordPress comme client et de centraliser le mail via un relais/endpoint de soumission.
Les serveurs web se font compromettre ; vous ne voulez pas que des webservers compromis aient le pouvoir d’envoyer directement des e-mails sortants.
9) Pourquoi les e-mails de réinitialisation échouent-ils plus souvent que les newsletters ?
Ils n’échouent pas forcément plus — on les remarque plus. De plus, les réinitialisations sont souvent déclenchées pendant des incidents (pics de trafic),
et leur timing est urgent. Tout retard de queue semble être une panne.
10) Est-il acceptable de désactiver la vérification TLS dans le plugin SMTP ?
Non, pas en production. Cela « corrige » le symptôme en supprimant la sécurité et rend le débogage plus difficile ensuite.
Corrigez les certificats et la confiance correctement. Vous voulez un comportement sécurisé et reproductible.
Conclusion : prochaines étapes qui tiennent
Un e-mail fiable n’est pas une question du plugin parfait. C’est avoir un vrai chemin de relais, une identité cohérente, et des journaux qui disent la vérité.
Construisez un endpoint de soumission, relayezz via un provider à moins que vous ayez vraiment besoin d’auto-héberger la réputation, et alignez SPF/DKIM/DMARC.
À faire cette semaine
- Exécutez le playbook de diagnostic rapide et classifiez la panne (remise vs réseau/auth vs délivrabilité).
- Standardisez la soumission SMTP (587) depuis WordPress/app vers un seul relais.
- Publiez/vérifiez SPF, DKIM et DMARC pour le domaine From que vous utilisez réellement.
- Ajoutez la surveillance de file et des logs afin de découvrir les problèmes avant que vos clients ne le fassent.
À faire ensuite
- Séparez les flux transactionnels et marketing si vous envoyez les deux.
- Faites tourner les identifiants, séparez prod/stage, et traitez les identifiants SMTP comme tous les autres secrets de production.
- Documentez le chemin de trace (intention app → ID file relais → résultat en amont) et intégrez-le à votre réponse aux incidents.
Rendez l’e-mail ennuyeux. Votre futur vous remerciera, probablement en silence, parce qu’il aura enfin du temps pour autre chose.