Oct 26, 2026 · 7 min read
Mes abonnés ne recevaient rien : les 4 erreurs qui envoyaient mes emails en spam

Copie cachée, SPF, DKIM, DMARC, List-Unsubscribe : ce que Gmail et Outlook regardent vraiment, expliqué simplement.
Chaque fois que je publiais un article, mon interface d'administration affichait fièrement « Article publié ! ». Le code envoyait ensuite un email à mes 7 abonnés pour les prévenir.
Sauf qu'aucun ne le recevait.
Pas d'erreur, pas de plantage, rien dans l'interface. Il a fallu qu'un abonné me le dise pour que je m'en rende compte. Et la réponse a fini par tomber : les emails arrivaient bien… directement dans leur dossier spam.
Voici ce que j'ai appris en cherchant pourquoi, et les 4 erreurs que j'ai corrigées. Que vous débutiez ou que vous codiez depuis dix ans, il y a de bonnes chances que votre application fasse au moins l'une d'elles.
Le résumé en 30 secondes
Si vous êtes pressé, voici la checklist :
- Un email par destinataire, jamais un envoi groupé en copie cachée (Cci).
- SPF, DKIM et DMARC configurés dans les DNS de votre domaine.
- Un lien de désabonnement en un clic, déclaré dans les en-têtes du mail.
- Un nom d'expéditeur lisible : « Junior Tchoffo », pas une adresse nue.
- Vérifiez le résultat : « envoyé » ne veut pas dire « reçu ».
La suite explique chaque point, avec le pourquoi.
Comment Gmail et Outlook décident qu'un mail est du spam
Premier réflexe faux : croire que le problème venait de mon code. Mon code faisait exactement ce qu'on lui demandait. Le mail partait, et mon serveur d'envoi (OVH) répondait « accepté ».
Le spam ne se décide pas chez vous. Il se décide à l'arrivée, chez Gmail, Outlook ou Yahoo, qui font passer chaque mail par leurs filtres avant de choisir entre la boîte de réception et le spam.

Ces filtres regardent, en gros, trois choses :
- L'authentification : ce mail vient-il vraiment de qui il prétend ?
- La forme du message : à quoi ressemble-t-il ? Personnel, ou envoi de masse anonyme ?
- La réputation : cet expéditeur a-t-il un historique ? Les destinataires ouvrent-ils ses mails, ou les signalent-ils ?
Mes 4 erreurs touchaient les deux premiers points. Et c'est une bonne nouvelle : ce sont ceux qu'on peut corriger dans la soirée.
Erreur n°1 : un seul mail en copie cachée
Mon code envoyait un seul mail, adressé à moi-même, avec les 7 abonnés en copie cachée (Cci). C'est pratique : un seul envoi, et personne ne voit les adresses des autres.
C'est aussi exactement ce que font les spammeurs.

Pour un filtre, un mail dont le destinataire ne voit même pas son adresse dans le champ « À » ressemble à un envoi de masse anonyme. À l'inverse, un mail adressé personnellement à awa@gmail.com ressemble à… un vrai mail.
Autre avantage : si une adresse est refusée (boîte pleine, faute de frappe), les autres abonnés reçoivent quand même le leur.
Pour les devs. Avec nodemailer, on passe d'un appel unique à une boucle.
// Avant : un seul mail, abonnés en copie cachée await transporter.sendMail({ from, to: from, bcc: abonnes, subject, html }); // Après : un mail par abonné for (const to of abonnes) { await transporter.sendMail({ from, to, subject, html }); }Envoyer en boucle depuis une fonction serverless convient pour quelques dizaines de destinataires. Au-delà, la fonction risque sa limite de temps : passez par un service d'envoi (Brevo, Resend, Postmark…) ou une file d'attente.
Erreur n°2 : un domaine sans DMARC
Quand vous postez une lettre importante, trois choses rassurent le destinataire. Ces trois choses ont chacune leur équivalent pour un email, sous forme d'enregistrements DNS de votre domaine.

- SPF, c'est la liste des facteurs autorisés. Elle dit : « seuls ces serveurs ont le droit d'envoyer des mails au nom de mon domaine ».
- DKIM, c'est le sceau de cire sur l'enveloppe. Chaque mail est signé, et le destinataire peut vérifier qu'il vient bien de vous et qu'il n'a pas été modifié en route.
- DMARC, c'est le règlement affiché à l'entrée. Il dit aux filtres quoi faire si SPF ou DKIM échoue (laisser passer, mettre en spam, refuser), et à qui envoyer des rapports.
Chez moi, SPF et DKIM étaient déjà en place : mon hébergeur mail les avait configurés. Il manquait DMARC. Sans lui, les filtres savent vérifier qui vous êtes, mais vous ne leur avez pas dit ce que vous attendez d'eux. C'est un signal de domaine « pas entièrement configuré ».
La bonne nouvelle : c'est une seule ligne. Ajoutez un enregistrement de type TXT dans les DNS de votre domaine :
Nom : _dmarc
Type : TXT
Valeur : v=DMARC1; p=none; rua=mailto:vous@exemple.com
p=none ne bloque rien : vous déclarez simplement que votre domaine est surveillé, et vous recevez des rapports sur l'adresse indiquée. Une fois que tout est propre, vous pourrez durcir la règle (p=quarantine, puis p=reject) pour empêcher qu'on usurpe votre domaine.
Le piège qui m'a fait perdre du temps. J'ai ajouté l'enregistrement chez mon registrar (là où j'ai acheté le domaine), qui m'a répondu : « Cette zone DNS n'est pas autoritaire ». Mes DNS étaient en réalité gérés par mon hébergeur de site, pas par le registrar. Avant de modifier vos DNS, vérifiez qui les gère : un outil comme
dig NS exemple.com, ou n'importe quel site de « DNS lookup », vous le dit en une seconde.
Erreur n°3 : pas de désabonnement en un clic
Mes mails contenaient bien un lien « Se désabonner » en bas de page. Mais pour Gmail et Outlook, un lien caché dans le texte ne suffit pas toujours.
Les clients mail savent afficher un bouton « Se désabonner » directement à côté du nom de l'expéditeur. Pour cela, le mail doit déclarer son lien dans ses en-têtes, avec List-Unsubscribe.
Pourquoi ça compte autant ? Parce qu'un lecteur qui ne trouve pas comment se désabonner clique sur… « Signaler comme spam ». Et chaque signalement abîme votre réputation. Offrir une sortie facile, c'est protéger vos futurs envois.
Depuis 2024, Gmail et Yahoo l'exigent des gros expéditeurs, et Outlook a suivi en 2025. Pour un petit site, ce n'est pas obligatoire. Mais c'est un signal de sérieux qui ne coûte presque rien.
Pour les devs. Deux en-têtes suffisent (norme RFC 8058) :
await transporter.sendMail({ from, to, subject, html, headers: { "List-Unsubscribe": `<${lienDesabonnement}>, <mailto:${adresseExpediteur}?subject=unsubscribe>`, "List-Unsubscribe-Post": "List-Unsubscribe=One-Click", }, });Le lien doit être propre à chaque abonné, et signé (par exemple avec un HMAC de son adresse). Sans signature, n'importe qui pourrait désabonner n'importe qui en devinant l'URL.
Erreur n°4 : un expéditeur sans nom
Dans la boîte de réception, mes mails apparaissaient comme venant de junior@…, sans nom. Ça paraît anecdotique. Mais entre « Junior Tchoffo » et une adresse brute, lequel ouvririez-vous en confiance ?
Le correctif tient en un format :
From: "Junior Tchoffo" <junior@exemple.com>
Un nom reconnaissable, c'est plus d'ouvertures et moins de signalements. Donc, avec le temps, une meilleure réputation.
Vérifiez chez vous en 5 minutes
Inutile de me croire sur parole : vous pouvez tester votre propre configuration.
- Dans Gmail, ouvrez un mail envoyé par votre application, cliquez sur les trois points ⋮, puis sur « Afficher l'original ». En haut, vous devez voir
SPF: PASS,DKIM: PASSetDMARC: PASS. UnFAIL, ou une ligne absente, vous dit exactement quoi corriger. - Sur mail-tester.com, le site vous donne une adresse temporaire. Envoyez-y un mail depuis votre application : vous obtenez une note sur 10 et la liste détaillée des problèmes.
Ce que ces corrections ne règlent pas
Soyons honnêtes : j'ai corrigé les 4 erreurs d'un coup. Je ne peux donc pas vous dire laquelle pesait le plus. Et la délivrabilité ne se résume pas à une checklist :
- La réputation se construit dans le temps. Les premiers envois d'un nouveau domaine sont regardés de près. Demander à vos premiers abonnés de cliquer sur « Ce n'est pas un spam » aide beaucoup.
- Le contenu compte aussi : un mail composé uniquement d'une grosse image, ou bourré de liens, reste suspect.
- Le volume change tout. Envoyer depuis votre propre code convient pour quelques dizaines d'abonnés. Pour des milliers, un service spécialisé gère la réputation, les rebonds et les désabonnements à votre place.
La vraie leçon : « envoyé » n'est pas « reçu »
Le plus inquiétant dans cette histoire, ce n'est pas le spam. C'est que mon interface me disait que tout allait bien.
« Article publié ! » voulait seulement dire que l'article était enregistré en base. Le mail, lui, pouvait échouer en silence ou finir en spam : je n'en savais rien.
Aujourd'hui, après chaque publication, mon interface affiche : « Serveur mail : 7 abonnés sur 7 acceptés ». Et je sais que même ce message ne garantit pas que le mail sera lu. Seule la vérification côté destinataire le dit.
C'est valable bien au-delà des emails : un message de succès n'est pas une preuve. Toute action importante devrait remonter son vrai résultat jusqu'à celui qui l'a déclenchée.
Pour aller plus loin : les recommandations de Google pour les expéditeurs d'emails et la norme RFC 8058 sur le désabonnement en un clic.