Quand un client me dit “on a un problème de délivrabilité”, je commence rarement par regarder l’objet, le design, ou la segmentation. Je vais directement chercher dans les logs SMTP et surtout dans les codes de retour. C’est simple et direct… mais c’est précis.

Les codes vous disent qui a dit non (vous, le relais, le domaine destinataire), pourquoi (adresse, politique, poids, cadence, réputation), et avec quelle gravité (temporaire vs définitif). En clair, ils transforment un “mon email n’arrive pas” en prise de décisions : retry, ralentir, nettoyer, corriger l’infra, ou supprimer.

Dans la série d’articles que je consacre aux bounces, celui-ci est surement le plus technique. Je n’entre pas dans l’impact business (réputation, revenus, blacklistage) qui est déjà couvert dans les autres volets et je laisse également de côté les “causes d’un bounce”. Ici, on passe côté back : comment sont structurés les codes, comment les lire rapidement, quels sont les pièges fréquents, et comment je normalise tout ça dans mes playbooks.


Les fondamentaux : où naissent les codes et comment les lire

1. Deux endroits où vous voyez des codes

  • Pendant le dialogue SMTP (synchrone)
    Votre serveur (ou votre ESP) parle au serveur destinataire : HELO/EHLO → MAIL FROM → RCPT TO → DATA. À chaque étape, le serveur d’en face répond avec un code à 3 chiffres (et une phrase). S’il refuse, c’est souvent là que vous verrez un 4xx (temporaire) ou un 5xx (définitif).
  • Après coup, dans un DSN (bounce message)
    Parfois, le message est accepté d’abord puis rebondit plus tard (ex. serveur intermédiaire, règle interne). Vous recevez alors un email de non-remise avec des Enhanced Status Codes du type 5.1.14.2.2, etc. C’est le format “X.Y.Z” (on y revient).

Pourquoi c’est important ? Parce que “qui” vous parle change la fiabilité du diagnostic. Un 550 pendant RCPT TO (“destinataire inconnu”) est quasi certain. Un 5.2.2 (“mailbox full”) dans un DSN peut dépendre d’une politique interne et donc être… un peu interprétable.

2. Les 3 chiffres classiques (codes SMTP)

  • 1er chiffre : la gravité
    • 2xx : succès
    • 3xx : attendez la suite (ex. 354 “Start mail input”)
    • 4xx : échec temporaire (soft) → on peut réessayer
    • 5xx : échec définitif (hard) → on ne réessaye pas
  • 2e chiffre : grande famille
    Sans tout réciter : x0x syntaxe, x1x information/adresses, x2x connexions, x3x non standard/mail system, x4x non standard/réseau. Dans la pratique moderne, retenez surtout le 1er chiffre et… les codes concrets ci-dessous.
  • Exemples fréquents
    • 421 Service not available (panne/maintenance) → soft
    • 450 Mailbox unavailable (temporaire) → soft
    • 451 Local error / policy temp → soft
    • 452 Insufficient system storage → soft
    • 550 Mailbox unavailable / user unknown → hard
    • 551 User not local → souvent hard (sauf redirection)
    • 552 Exceeded storage allocation → soft ou hard selon politique
    • 553 Mailbox name not allowed → plutôt hard
    • 554 Transaction failed / policy violation → hard (souvent)

3. Les Enhanced Status Codes (X.Y.Z)

Ils apparaissent souvent dans les DSN et affinent la raison :

  • X = Classe
    • 2 succès, 4 échec temporaire, 5 échec permanent.
  • Y = Sujet
    • 1 adresse, 2 boîte aux lettres, 3 système de messagerie, 4 réseau/routage, 5 protocole, 6 contenu/média, 7 sécurité/politique.
  • Z = Détail
    Le numéro précis (ex. .1 “inexistant”, .2 “désactivé”, .4 “trop gros”, etc.).

Exemples utiles (vous les verrez tout le temps)

  • 5.1.1 : destinataire inexistant → hard
  • 5.1.10 : problème d’adressage/routage → hard (souvent)
  • 5.2.1 : mailbox désactivée → hard
  • 4.2.2 : mailbox pleine → soft
  • 5.3.4 : message trop volumineux → souvent hard (selon domaine)
  • 4.4.1 : connexion expirée / timeout → soft
  • 4.4.2 : mauvaise connexion / réseau → soft
  • 5.4.1 : échec de routage → hard
  • 4.7.0 : politique/temporaire (greylisting, throttling) → soft
  • 5.7.1 : refus pour raisons de politique/sécurité (auth, spam) → hard
  • 5.7.26 : DMARC non conforme / émetteur non authentifié → hard (jusqu’à correction)

Raccourci : si vous voyez 4.x.x → soft ; 5.x.x → hard (avec quelques nuances côté 5.2.2 / 5.3.4 selon le fournisseur). J’y reviens plus bas avec ma logique de “bascule prudente”.


Ma check-list pour lire vite un bounce

  1. Regarder d’abord la classe : 4xx/4.x.x (soft) vs 5xx/5.x.x (hard).
  2. Identifier le sujet (Y) : 5.x.x
    • .1 = adresse ; .2 = boîte ; .3 = système ; .4 = réseau ; .5 = protocole ; .6 = contenu ; .7 = sécurité/politique.
  3. Décider l’action par défaut :
    • 5.1.15.2.1 → suppression immédiate (hard).
    • 4.2.24.4.14.7.0 → retries avec backoff (soft).
  4. Lire le texte “humain” : de nombreux domaines ajoutent un message clair (“mailbox full”, “unauthenticated due to DMARC”). C’est précieux pour trier les exceptions.
  5. Normaliser le motif (ma taxonomie interne) : user_unknown, mailbox_full, message_too_large, throttled, policy_block, auth_missing, etc.
  6. Décider les exceptions (rares, documentées) : exemple 5.3.4 “message too big” — j’allège et je réessaie une foissi le texte indique une politique fluctuante.

Liste des codes qui reviennent souvent et quoi en faire

Je regroupe par intention opérationnelle, pas par RFC. C’est comme ça que je les traite au quotidien.

1. Adressage et existence

  • 550 / 5.1.1 : destinataire inexistant (“user unknown”)
    Hard. Suppression immédiate + traçage de la source (collecte, import, partenaire).
    À faire : renforcer validation formulaire (syntaxe + MX), double opt-in, vérif temps réel.
  • 5.1.0 / 5.1.3 : adresse invalide (syntaxe)
    Hard. Vous auriez dû l’arrêter à la source.
    À faire : correction front + contrôle serveur.
  • 551 : user not local
    Plutôt hard. Exception si le message précise une redirection (forward-path).
    À faire : si pas de routage, supprimer.
  • 553 : mailbox name not allowed
    Hard. Souvent des caractères interdits ou adresse role-based bloquée par politique.
    À faire : politique claire sur les role-based + filtrage.

2. Boîte aux lettres et quota

  • 4.2.2 : mailbox full
    Soft. Retries avec backoff (3 à 5 tentatives), puis gel si récurrent.
    Piège : Certains domaines renvoient 5.2.2 (permanent) pour une boîte saturée de longue date. Je classe par défaut en soft, sauf si la description indique “persistant/over quota for long” → alors je bascule en hard après 2 campagnes.
  • 5.2.1 : mailbox disabled
    Hard. Adresse désactivée, inutile d’insister.
    À faire : suppression + audit source.

3. Taille et contenu du message

  • 5.3.4 : message too big
    Souvent hard (politique ferme). Je fais un correctif (alléger) et un test isolé, pas de retries en masse.
    À faire : compresser images, enlever pièces jointes, héberger les médias, minifier HTML.
  • 4.5.3 : too many recipients / limitations
    Soft. Limites de distribution (nombre de destinataires).
    À faire : scinder les envois, respecter les plafonds.

4. Connexion, réseau, cadence

  • 421 / 4.4.1 / 4.4.2 : indisponible, timeout, mauvaise connexion
    Soft. Le destinataire est KO ou vous êtes trop pressés.
    À faire : backoff, cadence par domaine, fenêtre d’envoi plus large, monitoring DNS/TLS.
  • 4.7.0 : throttling, greylisting, “try again later”
    Soft. C’est le “revenez doucement”.
    À faire : ralentir sur le domaine concerné. Ajouter retries espacés (15 min → 1 h → 4 h → 12 h). Réussite quasi systématique si réputation correcte.

5. Politique, sécurité, authentification

  • 5.7.1 : delivery not authorized / policy
    Hard. Refus politique ou sécurité (expéditeur, contenu jugé risqué, blocage domaine).
    À faire : vérifier SPF/DKIM/DMARC, éviter raccourcisseurs douteux, revoir tracking/redirections, contrôler la réputation du domaine de destination (landing/CDN).
  • 5.7.26 : DMARC/SPF/DKIM non conformes (expéditeur non authentifié)
    Hard tant que non corrigé.
    À faire : aligner domaine d’envoi et signatures (SPF qui autorise l’ESP, DKIM actif, DMARC en alignment correct). Je garde les détails de config pour l’article infra, ici je reste fonctionnel.
  • 454 / 5.7.0 : STARTTLS/Authentication temporairement indisponible
    Soft si 454Hard si 5.7.x récurrent.
    À faire : surveiller TLS, vérifier certificats, réessayer puis corriger.

6. Routage et DNS

  • 5.4.1 / 5.4.4 : échec de routage / unable to route
    Hard (souvent un domaine mal configuré côté destinataire, ou le vôtre est mal vu).
    À faire : tester la résolution DNS du domaine destinataire, vérifier votre propre HELO/PTR. On ne retry pas en masse.
  • 4.4.6 : routing loop detected
    Soft en théorie, mais c’est un vrai problème infra (chez l’autre).
    À faire : retries limités + log, puis abandon si persistant.

Cas d’usage concrets avec mon retour d’expérience

  • Le faux “soft” qui cache un “hard”
    Un domaine B2B renvoyait 4.2.2 mailbox full depuis… 6 semaines. Après deux campagnes consécutives sans évolution, j’ai basculé ces adresses en désactivation. Bénéfice : baisse de la pression et meilleure réputationglobale sur ce domaine.
  • Le 5.3.4 pas si définitif
    Une newsletter de lancement truffée de visuels passait en 5.3.4 chez un FAI très strict. Après minification + passage des guides en liens hébergés, test sur 1 000 adresses du même domaine : délivré. J’ai ré-ouvert l’adresse, mais une seule tentative après correctif, pas plus.
  • Le 5.7.26 qui a tout expliqué
    Campagne marketing OK partout, KO chez un grand webmail : 5.7.26. Diagnostic : l’ESP supplémentaire utilisé pour une partie du flux n’était pas déclaré dans SPF. Correction → fin des bounces “policy”.

Ma méthode de normalisation

Les libellés varient : “user unknown”, “no such user”, “unknown recipient”, “destinataire inconnu”… Je mappe tout vers une grammaire unique. Pourquoi ? Parce que je ne veux qu’une règle par motif, pas cinquante variantes.

Exemple de mapping :

CatégorieCodeLibelléType
Adressage5.1.1user_unknownhard
Adressage5.1.3 | 553address_syntax_invalidhard
Quota4.2.2 | 5.2.2mailbox_fullsoft par défaut, hard si persistant multi-campagnes
Contenu5.3.4message_too_largehard par défaut, retry test après allègement
Réseau4.4.1 | 421connection_timed_outsoft
Réseau4.7.0throttledsoft + cadence-par-domaine
Sécurité5.7.1policy_blockhard
Sécurité5.7.26auth_failedhard

Un conseil, implémentez ce mapping avant d’automatiser des décisions. Sinon, vous passez votre temps à courir après des synonymes.


Les décisions automatisées que j’applique partout

  1. Classement immédiat
    • 5.x.x → hard → suppression/quarantaine immédiate, sauf motifs explicitement listés comme “test post-correctif possible” (taille, politique spécifique).
    • 4.x.x → soft → retries (3 à 5, backoff 15 min → 1 h → 4 h → 12 h → 24 h).
  2. Bascule prudente
    • 5.2.2 mailbox full : classé soft si le texte indique surcharge temporaire ; hard si “persistant / long overdue”.
    • 5.3.4 : hard mais 1 test après allègement (pas d’inondation).
  3. Coupe après accumulation
    • Une adresse qui cumule soft sur 3 campagnes successives → désactivation (sunset).
    • Un domaine qui cumule throttled → réduction de cadence pour ce domaine (pas globalement).
  4. Périmètre
    • Je décide par adresse et par domaine. Beaucoup d’équipes n’agissent que par adresse et ratent l’optimisation par domaine (le vrai levier pour le throttling).

Les pièges classiques que je vois encore trop souvent…

  • Confondre le texte humain et le code
    Certains serveurs mettent des messages vagues (“policy issue”) avec un 5.1.1 (adresse) qui raconte autre chose. Je crois le code d’abord, puis je lis le texte pour nuances.
  • Traiter tous les 5.2.2 comme hard
    Vous risquez de jeter des boîtes pleines temporairement. Gardez une fenêtre de grâce (campagne suivante) avant la suppression, sauf si le texte dit “persistant”.
  • Réessayer un 5.1.1
    Non. C’est mort. Si vous réessayez, vous abîmez votre réputation pour rien.
  • Ralentir globalement au lieu de ralentir par domaine
    Vous punissez toute la base pour le comportement d’un seul FAI. La cadence par domaine est un multiplicateur de performance.
  • Ignorer la source d’acquisition
    Un pic de 5.1.1 ? Avant d’accuser “la base”, regardez le partenaire ou le formulaire qui a alimenté ce segment.

L’exception qui confirme la règle pour le code 250

“Mon email a été accepté (250)… et j’ai quand même reçu un bounce !” Ça arrive. On appelle ça parfois du backscatter (rebond en aval) ou simplement un refus différé. Explications rapides :

  • Votre message a été accepté par un relais (gateway), donc 250 OK.
  • Plus loin dans la chaîne (MTA interne, filtre antispam, MDA), il est refusé pour une raison interne (quota, politique, destinataire finalement inexistant).
  • Vous recevez un DSN avec un Enhanced Code (souvent 5.x.x).

À faire : Traitez ce DSN comme un bounce “classique”. Si c’est 5.1.1, on supprime. Si c’est 4.7.0, on met en place des retries. Et logguez que l’acceptation initiale n’était pas le verdict final.


La petite “antisèche” à garder dans un coin

  • Adresse invalide / inexistant : 5.1.1 → hard
  • Boîte désactivée : 5.2.1 → hard
  • Boîte pleine : 4.2.2 (parfois 5.2.2) → soft (puis gel si récurrent)
  • Message trop gros : 5.3.4 → hard (test après allègement, à petite dose)
  • Timeout / réseau : 4.4.14.4.2 → soft (retries + monitoring)
  • Throttling / greylisting : 4.7.0 → soft (cadence par domaine)
  • Blocage politique : 5.7.1 → hard (revoir auth/URL/landing)
  • DMARC/SPF/DKIM KO : 5.7.26 → hard (corriger alignements)

Comment j’industrialise la lecture des codes (sans devenir fou)

  1. Je collecte systématiquement les couples (code, texte) par tentative (pas seulement le dernier).
  2. Je mappe vers 15–25 motifs maison (cf. plus haut).
  3. J’applique des règles codées (hard/soft, retries, bascule, exceptions).
  4. Je segmente mes KPI par domaine et source d’acquisition (deux vues indispensables).
  5. Je boucle l’info vers l’équipe : collecte (si 5.1.1 monte), design (si 5.3.4 apparaît), ops (si 4.4.1 explose), deliverability (si 5.7.1/5.7.26 apparaissent).

Avec ça, moins de débats, plus d’actions. Vos bounces redeviennent prédictibles et vous pourrez enfin les éliminer correctement.


Les questions que je reçois le plus

“On voit 5.7.1 mais le contenu est hyper clean, ça peut venir d’ailleurs ?”
Oui : authentification (SPF/DKIM/DMARC), raccourcisseurs de liens mal réputés, domaine d’envoi incohérent, ou tracking trop verbeux (trop de redirections).

4.7.0 non stop chez un FAI, on fait quoi ?”
On ralentit pour ce domaine, on étale la campagne et on réaugmente graduellement quand les softs retombent.

5.2.2 chez un même contact très engagé la semaine dernière, possible ?”
Oui (boîte pleine en B2C). Je classe soft à court terme. Si ça persiste sur 2–3 campagnes, je gèle.

“On peut ignorer les Enhanced Codes et ne garder que les 3 chiffres ?”
Vous pouvez, mais vous perdez de la précision (adresse vs boîte vs contenu vs politique). Pour automatiser intelligemment, je recommande fortement de lire les deux.


Comment BounceStrike peut vous aider ?

Je sais que décoder ces codes à la main, au quotidien, c’est pénible. C’est exactement la raison d’être de BounceStrike :

  • Décodeur automatique des réponses SMTP et DSN (3-chiffres + Enhanced Codes) → on sort un motif normalisé clair (user_unknown, mailbox_full, throttled, policy_block, auth_failed, etc.).
  • Règles prêtes à l’emploi (hard/soft, retries, bascules prudentes pour 5.2.2/5.3.4) que vous pouvez adapter à votre tolérance risque.
  • Alertes par domaine : si 4.7.0 grimpe chez un FAI, on vous signale de ralentir pour ce domaine, pas pour toute la base.
  • API propre pour brancher votre ESP/CRM : plus besoin de jongler avec 50 synonymes de “user unknown”.

Si vous voulez, vous pouvez brancher BounceStrike sur un échantillon de vos envois pour que votre équipe sache précisément quoi faire à chaque cas. L’objectif n’est pas de tout changer dans votre stratégie emaling : c’est d’installer un pare-chocs qui transforme des logs illisibles en bonnes décisions.


Pour finir, les codes sont vos meilleurs alliés, si vous les domptez…

Un bounce sans code, c’est une devinette. Un bounce avec un code bien lu, c’est un plan d’action. Retenez la logique simple : 1) classe (4 = soft, 5 = hard), 2) sujet (adresse, boîte, réseau, contenu, politique), 3) règle (retry, alléger, ralentir, corriger auth, supprimer), 4) normalisation pour automatiser sans douleur.

Dans mon quotidien, cette approche me permet de :

  • couper net les hard qui n’ont aucune chance,
  • sauver ce qui mérite un second essai (soft),
  • diagnostiquer les pistes structurelles (collecte, cadence, contenu, infra),
  • et parler le même langage avec toute l’équipe (marketing, produit, ops).

Les codes ne sont pas là pour vous assommer : ils sont là pour vous rendre rapides et précis. Et si vous voulez raccourcir la route, BounceStrike peut devenir votre traducteur automatique de bounces, pour que chacun, chez vous, sache quoi faire dès qu’un 4.7.0 ou qu’un 5.1.1 apparaît.