Trackily Docs

Retours : rebonds différés et plaintes

Un e-mail accepté par ton serveur n'est pas un e-mail remis. Une boîte pleine, un domaine mort, un rejet en aval, ou un contact qui clique « C'est du spam » : tout ça arrive après l'envoi. Branche les retours, et Trackily retire ces adresses de tous tes envois, pour toujours — avant que ta réputation d'expéditeur ne s'effondre.

Pourquoi c'est indispensable

Sans retours, Trackily ne voit que les refus immédiats (le serveur SMTP refuse l'adresse pendant l'envoi). Tout le reste lui échappe :

  • le rebond différé : ton serveur accepte le message, essaie de le remettre, puis renvoie un avis de non-remise des minutes ou des jours plus tard (« User unknown », « Mailbox full ») ;
  • la plainte : le destinataire clique « C'est du spam ». Gmail, Outlook ou Yahoo le signalent à ton fournisseur d'envoi.

Si tu continues d'écrire à ces adresses, les messageries te le font payer : au-delà de 5 % de rebonds ou de 0,3 % de plaintes, tes e-mails passent en indésirables — y compris pour tes meilleurs contacts.

Comment ça marche

Une seule porte, secrète :

POST https://TON-TRACKILY/api/email/retours/<source>/<jeton>
  • <source> : brut (serveur maison), brevo, mailgun, postmark, sendgrid ou ses ;
  • <jeton> : 64 caractères aléatoires, générés dans Serveurs SMTP → Brancher les retours → Générer l'adresse secrète. Trackily n'en garde que l'empreinte (sha256) : il est montré une seule fois. Si tu le perds, régénère-le — l'ancien cesse de marcher à l'instant, et il faut recoller les nouvelles URL partout.

Sans le bon jeton, la porte répond 404 : pour qui ne l'a pas, elle n'existe pas. Le corps est limité à 1 Mo et à 1 000 événements par requête (toutes sources). Une adresse IP qui présente un jeton faux est limitée à 20 requêtes par minute ; avec le bon jeton, la limite est de 1 200 par minute — une rafale de vrais rebonds n'est jamais refusée.

Brancher chaque fournisseur

Copie l'URL de la source dans le tiroir « Brancher les retours », puis :

Brevo

  1. Brevo → Transactionnel → Paramètres → Webhook → Ajouter un webhook.
  2. Colle l'URL …/api/email/retours/brevo/<jeton>.
  3. Coche Hard bounce, Soft bounce, Email invalide, Bloqué et Plainte (inutile de cocher les ouvertures et les clics : Trackily les mesure lui-même).

Mailgun

  1. Mailgun → Sending → Webhooks → choisis ton domaine.
  2. Colle l'URL …/api/email/retours/mailgun/<jeton> sur Permanent Failure, Temporary Failure et Spam Complaints.

Postmark

  1. Postmark → ton serveur → ton flux (Default Transactional Stream ou ton flux de diffusion) → Webhooks → Add webhook.
  2. Colle l'URL …/api/email/retours/postmark/<jeton>, coche Bounce et Spam complaint.
  3. Coche aussi Include bounce content : Trackily y lit l'identifiant de l'envoi d'origine, le rattachement est alors exact.

SendGrid

  1. SendGrid → Settings → Mail Settings → Event Webhook.
  2. Colle l'URL …/api/email/retours/sendgrid/<jeton> en HTTP Post URL.
  3. Coche Bounced, Blocked et Spam Reports, puis active le webhook (Enabled).

Amazon SES (via SNS)

  1. Console AWS → SNS → Topics → Create topic (type Standard), par exemple ses-retours.
  2. Dans ce sujet : Create subscription → protocole HTTPS → colle l'URL …/api/email/retours/ses/<jeton>. Trackily confirme l'abonnement tout seul (il ne suit que les liens https://sns.<région>.amazonaws.com/… ; tout autre lien est refusé et journalisé).
  3. SES → Identities → ton domaine → Notifications → envoie Bounce et Complaint vers ce sujet, et coche Include original headers (rattachement exact).

Serveur maison (Postfix, Exim…)

Ton serveur reçoit lui-même les avis de non-remise (DSN, RFC 3464) et, si tu es inscrit aux boucles de retour des messageries, les rapports de plainte (ARF, RFC 5965). Il suffit de les transmettre bruts à Trackily.

  1. Fais aboutir l'adresse de retour (Return-Path) de tes envois à un alias. Dans /etc/aliases :

    bounces: "|/usr/local/bin/trackily-retour"
    

    puis newaliases.

  2. Crée le script /usr/local/bin/trackily-retour :

    #!/bin/sh
    # /usr/local/bin/trackily-retour — transmet l'avis brut à Trackily.
    curl -fsS --max-time 20 -H 'Content-Type: message/rfc822' \
      --data-binary @- "https://TON-TRACKILY/api/email/retours/brut/TON-JETON" >/dev/null || exit 75
    
  3. Rends-le exécutable et lisible de son seul propriétaire (le jeton y vit) : chown nobody /usr/local/bin/trackily-retour && chmod 700 /usr/local/bin/trackily-retour (Postfix exécute les tuyaux d'alias sous l'utilisateur nobody par défaut — default_privs).

Le || exit 75 n'est pas décoratif : seul le code 75 (EX_TEMPFAIL) fait différer et retenter Postfix. Avec n'importe quel autre code d'erreur (celui de curl tel quel), Postfix rejette l'avis — et comme un avis de non-remise a un expéditeur vide, ce rejet n'arrive nulle part : le rebond est perdu sans bruit. Avec exit 75, si Trackily est injoignable ou le réseau coupé, Postfix garde l'avis en file et le retransmet plus tard. Un avis transmis deux fois n'a aucun effet la seconde fois.

Pourquoi seul le Message-ID compte ici. La boîte des rebonds reçoit le courrier de n'importe qui : un avis arrivé par ce tuyau n'agit que si son Message-ID d'origine (aléatoire, posé par Trackily) correspond à un envoi et que son destinataire est celui de cet envoi. Un avis forgé avec la seule adresse d'un abonné, ou avec un X-Trackily-Send-Id (un numéro qui se devine), reste sans_envoi. Postfix renvoie l'en-tête Message-ID d'origine dans tout avis standard (partie text/rfc822-headers).

Essayer sans attendre un vrai rebond

Dans le tiroir, le bouton Essayer d'une source rejoue un rebond fictif (adresse rebond-essai@exemple.invalid) par le même analyseur que les vrais retours, sans rien écrire : ni suppression, ni journal. Tu vois ce que Trackily en comprend (type, code, diagnostic) et à quel envoi il l'aurait rattaché — ici aucun, puisque l'adresse fictive n'a jamais rien reçu : un vrai retour aurait l'effet sans_envoi.

L'essai vérifie la lecture, pas le branchement chez le fournisseur : pour ça, regarde la colonne « dernier reçu » de chaque source, ou utilise le bouton d'essai du fournisseur lui-même (Brevo, SendGrid et Postmark en ont un).

Ce que fait chaque type de retour

Trackily n'agit que sur un retour qui se rattache à un de ses envois — un faux avis ne peut pas désabonner une adresse au hasard. Pour un serveur maison (brut) : le Message-ID d'origine et le destinataire de cet envoi, rien d'autre. Pour un fournisseur (appel signé par le jeton), dans l'ordre : l'en-tête X-Trackily-Send-Id renvoyé et le même destinataire ; sinon le Message-ID d'origine ; sinon le dernier envoi parti à cette adresse dans les 30 jours. Le destinataire est lu dans Original-Recipient (l'adresse à laquelle Trackily a écrit, avant une redirection), sinon Final-Recipient ; les deux sont essayés. Rien de tout ça : effet sans_envoi, rien n'est touché.

Type Quand Ce que fait Trackily
Rebond définitif (rebond_dur) DSN Action: failed + statut 5.x.x ; Brevo hard_bounce/invalid_email ; Mailgun failed permanent ; Postmark HardBounce/BadEmailAddress ; SendGrid bounce ; SES Permanent — toujours avec un code de classe 5 (un 4.x.x n'est jamais définitif) L'adresse entre dans la suppression (raison hard_bounce) ; toutes ses lignes d'abonné passent bounced ; l'envoi rattaché passe bounced ; un événement bounce ; les compteurs des listes sont rafraîchis.
Rebond temporaire (rebond_doux) statut 4.x.x, quel que soit le libellé du fournisseur ; boîte pleine (5.2.2 comme 4.2.2) ; soft_bounce ; temporary ; SoftBounce ; SES Transient ; SendGrid blocked Noté (événement bounce_soft), sans suppression. Mais trois rebonds temporaires sur trois envois distincts en 30 jours, sans aucune ouverture ni aucun clic depuis le premier, valent un rebond définitif (raison rebonds_temporaires_repetes).
Plainte (plainte) ARF Feedback-Type: abuse ; Brevo spam ; Mailgun complained ; Postmark SpamComplaint ; SendGrid spamreport ; SES Complaint Suppression (raison complaint) ; toutes les lignes de l'adresse passent complained ; un événement complaint.
Ignoré (ignore) livraisons, ouvertures, différés (delayed, deferred), désinscriptions venues du fournisseur, Mailgun suppress-* (Mailgun n'a rien tenté : l'adresse était déjà sur sa liste)… Journalisé, sans effet.
Illisible (illisible) un avis que Trackily ne sait pas lire Journalisé (le fournisseur reçoit quand même 200), sans effet.

Jamais contre le serveur. Un rebond qui accuse ton serveur d'envoi — IP sur une liste de blocage (Spamhaus, SpamCop, « block list » de Microsoft…), IP refusée, réputation, limitation de débit (Yahoo TSS04, Gmail 4.7.28…), tout code x.7.x (sauf un motif explicite d'adresse inconnue), relais ou identifiant refusé, blocked côté fournisseur — n'est pas la faute de l'adresse : il est noté comme rebond temporaire, ne compte pas dans les trois, et ne supprime jamais. Sinon, une IP mise sur liste noire viderait tes listes en une matinée.

Une adresse déjà dans la suppression y garde sa raison d'origine (effet deja_supprime). Un même retour reçu deux fois (le fournisseur réessaie) n'a d'effet qu'une fois.

Où lire les retours

  • Suppression → Retours reçus : le journal (180 jours), filtrable par type, source, et adresse.
  • Serveurs SMTP → un serveur → Retours (7 jours) : rebonds définitifs, temporaires, plaintes et leurs taux (à partir de 20 envois). Au-delà de 5 % de rebonds ou de 0,3 % de plaintes, le serveur affiche un avertissement — jamais un blocage. Et dès qu'un retour « faute du serveur » (liste de blocage, réputation, limite) arrive pour ce serveur, l'avertissement « Ton serveur est signalé » dit combien en 24 h, depuis quand, et le début du dernier diagnostic (sans aucune adresse).
  • Chaque ligne du journal dit à qui la faute (faute : adresse, serveur, ou rien quand elle ne se juge pas) : une note « Faute du serveur d'envoi » n'accuse pas l'adresse.
  • Envois ponctuels → un envoi : ses rebonds et ses plaintes.
  • MCP : get_email_returns_config, list_email_returns, test_email_return (l'essai), et regenerate_email_returns_token (en deux temps, avec confirmation).

Ce qui n'est pas couvert

  • la lecture d'une boîte par IMAP ou POP : le tuyau d'alias couvre les serveurs maison sans dépendance ;
  • les signatures natives des webhooks (Mailgun, SNS) : c'est le jeton de l'URL qui fait foi — garde-le secret ;
  • un rapport de plainte qui masque le destinataire (certaines messageries le font) : sans adresse, il ne se rattache à rien (sans_envoi).

Voir aussi

  • Suppression — la liste noire globale que les retours alimentent
  • SMTP — refus immédiats, erreurs de serveur, verdict « Peut envoyer ? »
  • Envois ponctuels — statistiques d'un envoi