Comment déboguer “Envoyé mais non reçu” : la méthode d’une équipe produit (de bout en bout)
Le signal est presque toujours le même : un utilisateur vous écrit “j’ai cliqué sur Envoyer, ça affiche Envoyé, mais je n’ai rien reçu”. Et côté produit, c’est l’un des tickets les plus pénibles, parce que la vérité est rarement dans une seule couche : parfois c’est l’app, parfois l’ESP (Email Service Provider), parfois le DNS, parfois une politique anti-spam, parfois un bounce silencieux, parfois juste… un délai.
La bonne approche n’est pas de “regarder si l’e-mail est parti”, mais de reconstituer la chaîne complète : UI → backend → file d’envoi → ESP → SMTP → réception → boîte de l’utilisateur. Une équipe produit efficace traite ce type d’incident comme un mini-incident de fiabilité : on collecte des preuves, on suit une piste, et on transforme le correctif en prévention (instrumentation, alertes, checklists).
1) Clarifier le symptôme exact (avant d’ouvrir les logs)
“Non reçu” peut vouloir dire plusieurs choses. La première étape est donc de qualifier, sans jargon, avec des questions fermées et utiles :
- Quel type d’e-mail ? (OTP, validation d’inscription, reset mot de passe, reçu de paiement, notification)
- Quelle adresse destinataire ? (copier-coller exact, éviter les espaces, vérifier le domaine)
- Quand ? (heure locale + fuseau, et nombre de tentatives)
- Quel canal ? (web, iOS, Android, API, intégration partenaire)
- Est-ce intermittent ? (parfois ça arrive, parfois non) ou systématique ?
- Le message arrive-t-il ailleurs ? (spam, promotions, indésirables, onglets)
- Un autre destinataire reçoit-il ? (test sur Gmail/Outlook/Yahoo)
Ce mini-questionnaire vous évite 80% des fausses pistes. Par exemple : si ça ne marche que pour un domaine (ex. Outlook) et pas pour Gmail, vous êtes déjà sur une piste “délivrabilité/domaine” plutôt que “bug applicatif”.
2) Définir une règle d’or : “Envoyé” côté UI ≠ “Livré” côté e-mail
Dans beaucoup de produits, l’UI affiche “Envoyé” dès que le backend a accepté la demande, pas quand l’e-mail est réellement remis à la boîte du destinataire. C’est normal… mais dangereux pour la confiance.
Une équipe produit doit donc expliciter en interne (et idéalement dans le produit) trois niveaux :
- Accepted : on a reçu la requête et l’on a créé une tâche d’envoi.
- Queued/Submitted : l’ESP a accepté le message (ID de message, statut “accepted”).
- Delivered : l’ESP annonce une remise réussie (ou un événement de livraison).
Le débogage consiste à trouver à quel niveau la chaîne se brise.
3) Le playbook produit : remonter la chaîne en 6 étapes
Étape 1 — Côté produit : vérifier la logique d’envoi
Avant d’accuser l’ESP, vérifiez le plus simple :
- Le bouton “Envoyer” déclenche-t-il bien l’API attendue (endpoint, payload, headers) ?
- Y a-t-il un rate limit ou une protection anti-abus (par IP, par compte, par appareil) ?
- Le backend déduplique-t-il les demandes (idempotency) et pourrait-il “ignorer” la seconde ?
- Le destinataire est-il normalisé (lowercase, trim) ? Un espace final peut suffire à casser un envoi.
- Le cas “déjà inscrit” est-il géré ? Certains parcours masquent l’échec pour éviter l’énumération.
Point produit très fréquent : pour éviter de révéler l’existence d’un compte, on affiche le même message (“Si cette adresse existe, vous recevrez un e-mail”). C’est une bonne pratique de sécurité, mais cela signifie que “Envoyé” peut être volontairement non-affirmatif. Votre support doit le savoir.
Étape 2 — Backend : trouver la trace (correlation ID)
Si vous n’avez pas de correlation ID ou d’ID de requête pour suivre l’envoi, vous perdez du temps à chaque incident. Dans un monde idéal :
- Chaque demande d’envoi génère un request_id.
- La tâche en file (queue) a un job_id.
- L’ESP renvoie un provider_message_id.
- Les événements (bounce, delivered, complaint) sont rattachés à ce même fil.
En investigation : vous partez du ticket utilisateur (adresse + timestamp) et vous trouvez la ligne “accepted” côté backend. Si vous ne la trouvez pas, ce n’est probablement pas un problème d’e-mail : c’est la requête qui n’a pas été déclenchée, ou a été rejetée avant l’envoi.
Étape 3 — Queue / worker : vérifier l’exécution réelle
Un grand classique : l’API répond 200, la tâche est créée, mais :
- le worker est down,
- la queue est saturée,
- un déploiement a cassé une dépendance,
- ou une exception empêche l’envoi (template manquant, variable null, timeouts).
Indicateurs utiles :
- Lag de queue (temps moyen avant traitement)
- Taux d’échec worker (retries, DLQ)
- Temps d’envoi (latence de l’appel à l’ESP)
Du point de vue produit, si le problème est un retard, la bonne réponse UX n’est pas “Envoyé”, mais “En cours, cela peut prendre quelques minutes”. La nuance réduit immédiatement la frustration.
Étape 4 — ESP : accepté ou rejeté ?
Une fois l’appel à l’ESP confirmé, cherchez le statut côté provider :
- Accepted : l’ESP a accepté la demande, mais la livraison n’est pas garantie.
- Rejected : problème de contenu, domaine, réputation, politique, ou quota.
- Bounced : rejet par le serveur destinataire (adresse invalide, boîte pleine, politique).
- Suppressed : l’ESP bloque automatiquement (hard bounce précédent, plainte spam, désinscription, liste noire interne).
La “suppression list” est une cause très fréquente de “sent but not received” : vous envoyez, votre système dit OK, mais l’ESP n’envoie même plus vers cette adresse parce qu’elle a historiquement échoué ou s’est plainte.
Étape 5 — DNS et authentification : SPF / DKIM / DMARC
Si votre délivrabilité est instable, ou si certains domaines (souvent Outlook/Hotmail, parfois Yahoo) sont touchés, vérifiez l’authentification :
- SPF : autorise les serveurs à envoyer pour votre domaine.
- DKIM : signe cryptographiquement le message (integrité + réputation).
- DMARC : politique de traitement et reporting, alignement SPF/DKIM avec le domaine visible.
Du point de vue produit, ce n’est pas juste “un truc de DNS” : ce sont des prérequis de confiance. Un changement de domaine d’envoi, une migration d’ESP, ou un sous-domaine mal configuré peut créer des pertes silencieuses, difficiles à détecter sans métriques.
Étape 6 — Réception : spam, onglets, filtrage entreprise, délais
Même si l’ESP annonce “delivered”, l’utilisateur peut ne rien voir :
- Classement automatique (onglet Promotions, Notifications).
- Filtre entreprise (gateway) qui quarantine.
- Client mail qui trie agressivement (règles, filtres, alias).
- Délai de propagation (plus rare, mais réel).
Une bonne pratique produit consiste à ajouter une aide “où chercher” : “Vérifiez Indésirables/Promotions, et recherchez le sujet ou notre domaine”. C’est un micro-texte qui réduit la charge support.
4) Étude de cas (courte) : quand “tout est vert” mais rien n’arrive
Imaginez une équipe produit qui lance une fonctionnalité “Connexion par code”. Les métriques de l’API montrent une hausse d’usage, et pourtant, le support voit monter : “je ne reçois pas le code”. La première réaction est de suspecter l’ESP. Mais les logs backend montrent “accepted”, la queue est stable, l’ESP affiche “accepted” aussi.
La clé apparaît en comparant les destinataires : une majorité de tickets sont sur des adresses professionnelles. En creusant, on découvre que l’e-mail est livré… au filtre de sécurité de l’entreprise, qui le met en quarantaine car le domaine d’envoi a changé récemment et le DMARC n’est pas aligné. L’utilisateur final ne voit rien, l’ESP dit “delivered”, et le produit disait “Envoyé”.
Correctifs durables : alignement DMARC, signature DKIM sur le bon sous-domaine, ajout d’un lien “Renvoyer le code”, et un message UX plus précis (“Cela peut prendre 1–2 minutes, vérifiez Indésirables”). Résultat : baisse nette des tickets et meilleure confiance.
5) Checklists rapides : diagnostiquer en moins de 10 minutes
Checklist “incident en cours” (triage)
- Le problème touche-t-il un domaine (ex. Outlook) ou tous ?
- Le problème touche-t-il un type d’e-mail (OTP) ou tous ?
- La queue a-t-elle du retard (lag) ?
- Le taux de bounce/suppression a-t-il augmenté ?
- Un déploiement récent a-t-il touché templates, worker, DNS, domaine d’envoi ?
Checklist “preuve minimale” à collecter
- adresse destinataire (exacte) + timestamp + fuseau
- type d’e-mail + endpoint déclenché
- request_id / job_id
- provider_message_id
- statut ESP (accepted/bounced/suppressed/delivered)
6) Améliorations produit qui réduisent drastiquement ces tickets
1) Bouton “Renvoyer” avec garde-fous
Le simple fait d’avoir “Renvoyer le code” (avec limitation) réduit la frustration. Côté produit, cela transforme un incident “bloquant” en un “contretemps”. Ajoutez un cooldown (ex. 30–60 secondes) pour éviter l’abus.
2) Indiquer une attente réaliste
Remplacer “Envoyé” par une formulation plus fiable : “Demande prise en compte. Si vous ne recevez rien sous 2 minutes, réessayez.” L’objectif n’est pas de se dédouaner, mais d’être honnête sur le système.
3) Instrumentation par étape
Créez des métriques par étape : accepted_backend, queued, submitted_to_esp, delivered, bounced, suppressed. Sans cette visibilité, vous dépendez des tickets pour découvrir un problème.
4) Gestion des suppressions
Si l’ESP a une liste de suppression, prévoyez une procédure interne : comment la consulter, comment demander une levée, comment éviter de ré-envoyer vers une adresse “hard bounced” sans logique claire. Une partie du travail est produit : décider de l’expérience utilisateur quand l’adresse est suppressée (message générique, alternative, support).
5) Tests multi-domaines (pré-prod et post-déploiement)
Un test e-mail qui ne cible que Gmail est insuffisant. Ajoutez des tests réguliers vers Gmail + Outlook + Yahoo, et idéalement une adresse entreprise. C’est une assurance contre les régressions de délivrabilité.
7) Quand escalader (et vers qui) : décision produit
Une équipe produit gagne du temps si elle a une règle claire d’escalade :
- Pas de trace backend → équipe API / web / mobile (bug de déclenchement, auth, rate limit).
- Trace backend OK, worker KO → plateforme / SRE (queue, retries, déploiement).
- ESP rejected/suppressed → owner délivrabilité + support ESP (politiques, listes, quotas).
- Delivered mais non visible → délivrabilité + guidance utilisateur (spam, filtres entreprise).
La maturité produit, ici, c’est de ne pas laisser le support “deviner”. Un arbre de décision simple, documenté, transforme le chaos en routine.
Conclusion : un incident fréquent, mais totalement maîtrisable
“Envoyé mais non reçu” n’est pas un mystère : c’est un symptôme multi-couches. En adoptant une approche produit — qualification claire, preuves minimales, remontée de chaîne, puis prévention — vous passez d’un ticket frustrant à un processus fiable.
Le vrai levier, au-delà du débogage, c’est la transparence : distinguer “demande acceptée” de “livraison confirmée”, instrumenter les étapes, et offrir à l’utilisateur une solution simple (renvoi, délai réaliste, aide de recherche). C’est exactement ce qui fait la différence entre un produit qui “semble capricieux” et un produit qui inspire confiance, même quand l’infrastructure e-mail n’est pas parfaite.