From:reste l’adresse lisible que les destinataires voient et à laquelle ils répondent.Return-Path:(le MAIL FROM d’enveloppe) est une boîte technique dédiée qui collecte les notifications de statut de livraison, pour que le traitement des bounces ne fouille jamais le courrier ordinaire d’une personne.
Un grant élargit l’enveloppe seulement. Le header
From: garde sa propre porte : il doit toujours être une identité du compte authentifié. Et un grant n’est pas un alias : il n’implique aucune délivrance et ne crée aucune identité. C’est de l’autorisation pure.Comment ça marche
Un grant autorise toute local-part d’un domaine comme MAIL FROM. La granularité domaine est délibérée : le traitement des bounces frappe normalement une enveloppe différente par destinataire (VERP,bounce+alice=example.com@bounces.example.org), donc des règles par adresse ne pourraient jamais suivre. Un domaine accordé couvre toutes les variantes VERP. La preuve appartient au domaine du tenant, comme toute preuve de domaine d’envoi : une fois qu’elle tient, tout compte ordinaire du tenant peut utiliser le domaine comme MAIL FROM, et le compte que vous nommez à add est celui dont les identités servent à vérifier la règle de même organisation ci-dessous.
Deux garde-fous s’appliquent à la création du grant, pas découverts plus tard :
- Le courrier du domaine doit revenir à ce serveur. Le grant n’autorise rien tant que tous les enregistrements MX du domaine ne nomment pas le nom d’hôte du serveur (
[server] hostname), ou que le domaine n’a pas de MX et est ce nom d’hôte (le MX implicite de la RFC 5321 §5.1, qui n’exige aucun changement DNS). Un return-path est l’endroit où arrivent les bounces et les plaintes : la preuve qui compte est donc qu’ils arrivent ici. Elle remplace l’enregistrement TXT_oximail-envelopeque les grants demandaient auparavant. Un MX ailleurs, ou un MX nul, suspend le grant fail-closed ; une erreur DNS transitoire ne le fait jamais. La preuve est revérifiée deux minutes après le démarrage du serveur, puis toutes les six heures, et une preuve qu’aucun contrôle n’a confirmée depuis 72 heures (des serveurs de noms qui ne répondent plus) cesse aussi d’autoriser. Dans les deux cas, les envois sous ce domaine sont différés451 4.7.1, pas rejetés : la file de la plateforme retente pendant que la preuve revient. La métriqueoximail_envelope_domain_suspended_totalcompte les suspensions, etoximail doctorcontrôle chaque preuve soussender_domain_proofs. - La règle de même organisation. Le domaine accordé doit partager son domaine organisationnel avec une identité du compte.
bounces.example.orgpeut être accordé àsender@example.org;bounces.other.netnon. C’est la règle d’Amazon SES, et c’est ce qui garde SPF aligné sous DMARC par construction : un Return-Path hors organisation casse DMARC en silence chez certains récepteurs des semaines plus tard, alors OxiMail le rend irreprésentable plutôt que de le documenter en avertissement.
Mise en place
Disons que la plateforme s’authentifie commesender@example.org et que vous voulez collecter les bounces dans une boîte dédiée.
bounce@ (IMAP), et réglez son Return-Path sur une adresse du domaine accordé. Terminé : la plateforme envoie comme sender@, les destinataires voient sender@, et chaque DSN atterrit dans bounce@. Un rapport qu’OxiMail rédige lui-même porte le Message-ID d’origine dans sa troisième partie (les en-têtes d’origine par défaut, le seul Message-ID pour un message expiré dans la file), et c’est par lui qu’une plateforme comme MailWizz attribue un rebond ; une soumission qui n’avait pas de Message-ID en a reçu un du serveur à la soumission.
VERP sans aucun travail serveur supplémentaire
Si la plateforme frappe des enveloppes par destinataire (VERP), faites-lui utiliser un plus-tag de la boîte de bounce :bounce+<abonné>@bounces.example.org. Le grant autorise chaque variante (toute local-part du domaine passe), et le plus-addressing d’OxiMail les délivre toutes nativement dans la boîte de bounce@. Pas de catch-all, pas de configuration serveur.
La répartition des rôles est délibérée, et c’est celle de toute l’industrie : le serveur de mail autorise et garde DMARC aligné ; la plateforme de listes frappe les enveloppes et dépouille les bounces. OxiMail ne génère pas d’adresses VERP et ne gère pas la cadence d’envoi : votre plateforme fait déjà les deux, et les règles des grands récepteurs (désabonnement en un clic, plafonds de taux de plainte) sont aussi ses obligations : un flux de masse vérifie que les en-têtes de désabonnement en un clic sont présents, il ne les écrit jamais.
Quand un envoi est refusé
Un MAIL FROM qui ne correspond à aucune identité et à aucun grant jamais vérifié est rejeté en fin de DATA :envelope-domain verify et revérifiez le MX du domaine.
Un grant vérifié puis suspendu, ou non revérifié depuis 72 heures, répond plutôt 451 4.7.1 (« Envelope-sender domain proof is not current ») : un état réversible, donc une réponse transitoire que la plateforme retente dans sa propre fenêtre d’abandon. envelope-domain list l’affiche comme suspended ou stale ; rétablissez le MX ou le DNS du domaine, puis lancez envelope-domain verify.
Retirer un grant
--yes est requis, comme pour tout verbe destructif.
Envoyer à grande échelle
Une plateforme qui envoie des milliers de messages n’est pas une personne, et la même box porte les deux. Quatre mécanismes les séparent. La route, la classe, la signature et les en-têtes décrits ici sont servis aujourd’hui ; l’admission (la décision d’accepter ou de refuser une soumission selon son flux) ne l’est pas encore : voir l’encadré plus bas.Les flux d’envoi
Un flux est l’unité qui envoie. Il appartient à un compte, et c’est l’identifiant qui ouvre la session SMTP qui le choisit : un mot de passe d’application lié au flux, ou le mot de passe du compte lui-même pour l’unique flux créé avec--account-login. Un flux a un rôle, exclusif sur un même compte :
origination: une application qui émet. Son courrier est à compléter et à signer par le serveur (avec une clé de l’opérateur ou une clé déléguée, et une cosignature si son pool en a une). Quand l’admission sera appliquée, sonFrom:sera jugé d’après les domaines prouvés du tenant plutôt que d’après les identités du compte.transit: une leaf qui signe elle-même, transférée à l’octet près comme l’est le courrier d’un compte relais. Aujourd’hui, ce comportement est décidé par le rôleservicedu compte.
--apply (--yes pour suspend et delete) ; list et show --flow <id ou nom> acceptent --json. Le nom est unique sur le compte (A-Za-z0-9._-, 1 à 64 caractères). --bulk déclare un envoi de masse. --retention kept|ephemeral (kept par défaut) est enregistré sur le flux ; ce qui rend éphémère le courrier d’un compte relais reste son rôle service (rétention), pas ce champ. suspend --flow … --reason … --yes met un flux en pause, resume --apply lève la pause, delete --yes est refusé tant qu’un mot de passe d’application est lié au flux. Un compte qui porte des flux, atteint par un identifiant qui n’en désigne aucun, n’est jamais pris pour une personne.
Ce qu’un flux change aujourd’hui :
- sa classe dans la file (plus bas) : masse si le flux est déclaré de masse, transactionnelle sinon, et une soumission sans flux reste celle d’une personne ;
- son adresse : le pool de sortie nommé par
set-pool, pour le courrier mis en file à partir de là (un DSN ou un rapport de relais hérite de la route de la ligne à laquelle il répond ; une soumission JMAP ne porte aucun flux et part de l’adresse par défaut) ; - ses en-têtes : le message d’un flux d’origination part avec
X-OxiMail-Flow: <id du flux>(c’est ainsi qu’une plainte retrouve son flux) et, quand le client n’en a mis aucun, unFeedback-ID: <flux>:<tenant>:<bulk|tx>:<nom d'hôte du relais>(identifiants opaques, aucune donnée personnelle). UnX-OxiMail-Flowécrit par un client est retiré de toute soumission ordinaire : une valeur copiée imputerait à un autre flux ses plaintes ; - ses compteurs : les destinataires distants livrés, et les plaintes, par flux (plus bas).
Les pools de sortie
Par défaut, chaque message part de l’adresse par défaut de la box et annonce le nom HELO de la box. Une campagne ne doit pas partager l’adresse d’où les personnes envoient : la réputation se tient par adresse. Un pool de sortie est une adresse (ou une par famille) et son HELO, déclarés dans la configuration parce que c’est un fait de l’hôte :
Une clé inconnue fait refuser le fichier. Chaque adresse locale est liée une fois au démarrage ; une adresse qui n’est sur aucune interface de la machine empêche le démarrage. Un pool s’ajoute avec un redémarrage, et
set-pool avertit quand il nomme un pool que la configuration chargée ne contient pas.
Jamais de repli. Une ligne dont le pool est absent de la configuration, ou n’a pas d’adresse dans la famille à laquelle la box est figée, attend : aucune tentative n’est comptée et l’expiration ne bouge pas. Un message de masse ne part jamais de l’adresse d’où les personnes envoient. Le pool entre dans chaque clé que le travailleur partage (la session réutilisée, les créneaux par hôte, le disjoncteur d’hôte) : une campagne ne roule donc jamais sur une session ouverte depuis l’adresse par défaut, et le disjoncteur ne bat pas entre deux adresses. Un pool qui a une adresse IPv4 et une adresse IPv6 joint une destination qui n’a que de l’IPv6 depuis son IPv6, et tout le reste depuis son IPv4 : voir sur quelle famille IP le courrier part. Les adresses publiques des pools comptent comme celles de cette box pour la détection de boucle, et leurs adresses IPv4 publiques rejoignent la surveillance de réputation.
Un pool dédié au courrier de masse est recommandé, pas exigé : un flux de masse qui n’en a pas partage l’adresse par défaut avec les personnes, et les classes ci-dessous protègent alors la latence, pas la réputation. oximail doctor contrôle chaque pool sous egress_pools : chaque adresse locale est sur une interface, et avec --reachability chaque adresse publique a un DNS inverse confirmé à l’aller sur le HELO et le SPF du HELO la laisse passer.
Les classes de file
Le courrier sortant attend dans trois classes, servies dans cet ordre : humain (human), transactionnel (transactional), masse (bulk). La classe est décidée une seule fois, à la mise en file du message, et stockée sur la ligne de file.
Un rapport de livraison (DSN) ou un rapport de relais hérite de la classe de la ligne qui l’a produit. Un compte sans flux qui écrit à plus de 200 destinataires sur une heure glissante est rétrogradé en transactionnel pour la suite, jamais refusé.
Le répartiteur de livraison fait tourner 16 créneaux de livraison (
[smtp.dispatcher] global_slots, borné par la taille du pool de la base moins 4 ; il n’en faisait tourner que 4 parce qu’il lisait un défaut périmé). La masse n’en tient jamais plus de 12, et les deux derniers sont réservés aux personnes seules (le courrier transactionnel ne les prend pas non plus) ; la masse laisse libre le quart du budget d’octets en vol et le transactionnel un huitième, mais seulement tant qu’autre chose tient des octets ; et des deux créneaux de connexion vers chaque hôte distant, un est gardé pour les personnes. Mesuré sur un banc, le message d’une personne vers un hôte qu’une campagne de 5 000 messages remplissait est parti en 107 ms, pendant que 4 989 messages de masse attendaient encore.
oximail doctor rapporte queue_classes : en attente, en envoi et l’âge de la plus ancienne ligne jamais tentée par classe, et il échoue quand le message d’une personne a attendu plus de 60 secondes sans tentative pendant que de la masse part, ce qui veut dire que les budgets ne tiennent pas. Les mêmes chiffres sont oximail_smtp_queue_class_depth{class}, oximail_smtp_queue_class_in_flight{class}, oximail_smtp_queue_class_oldest_unattempted_seconds{class} et la jauge de famine oximail_smtp_queue_human_starved. queue_depth ne fixe de seuil que pour le courrier des personnes et le transactionnel : une campagne est une ligne par destinataire, donc la profondeur de la masse s’affiche, elle ne se juge jamais.
Les exigences des grands fournisseurs
Les grands fournisseurs de messagerie demandent aux expéditeurs de masse un désabonnement en un clic signé, un domaine avec DMARC et un faible taux de plainte. Le relais mesure chacun d’eux et, une fois l’admission appliquée, l’applique. Plaintes. La plainte d’un fournisseur (un rapport ARF, RFC 5965) envoyée à l’adresse de boucle de retour du relais est comptée contre le flux qui a envoyé le message signalé. À vous d’inscrire l’adresse aux boucles de retour des fournisseurs, puis de la nommer :forward est actif. Une plainte n’est crue que si le rapport a passé DMARC pour un fournisseur listé, si l’original signalé porte exactement un X-OxiMail-Flow qui désigne un flux d’origination existant, et si son domaine From: est prouvé par le tenant de ce flux. Tout le reste est journalisé avec sa raison et jamais compté, parce qu’une plainte peut mettre un flux en pause et qu’une plainte forgée est une attaque contre un client. Ce qui est conservé : le flux, le fournisseur, le Feedback-Type et la date, jamais le message signalé ni son destinataire. Gmail n’envoie aucun rapport de plainte : Postmaster Tools lit le Feedback-ID à la place, que la signature couvre.
Taux de plainte. Les destinataires distants livrés sont comptés par flux à la fin de la livraison. Chaque heure, le relais juge les sept derniers jours, à partir de 1 000 destinataires livrés et 3 plaintes : 0,1 % déclenche une alerte et 0,3 % met le flux en pause (la raison de la pause nomme le taux). oximail doctor affiche le taux de chaque flux sous complaint_rates, avertit dès le seuil d’alerte et nomme un flux en pause avec le verbe qui la lève, oximail account flow resume --email … --flow … --apply, qui journalise ce qu’il a levé. Les compteurs sont gardés 30 jours.
Garde de masse. Pour un flux déclaré de masse, un message doit porter un List-Unsubscribe avec un List-Unsubscribe-Post: List-Unsubscribe=One-Click (RFC 8058), et son domaine From: doit publier DMARC (son propre enregistrement _dmarc, sinon celui de son domaine organisationnel). Des en-têtes manquants ou un domaine sans DMARC sont des refus (5xx). La réponse DMARC est lue dans un cache et jamais interrogée pendant la réception du message : un domaine pas encore connu est différé 451, et le relais le résout en moins d’une minute, le rafraîchit chaque jour, et récupère d’avance chaque domaine qu’un flux de masse peut utiliser (une preuve dkim ou de return-path vérifiée et non suspendue), si bien que le premier message d’un domaine nouvellement prouvé n’attend pas.
Signature. Elle couvre la paire de désabonnement, Feedback-ID et X-OxiMail-Flow, comme le demande la RFC 8058 §4 (qui signe quoi).
Le taux de plainte est compté et la garde évaluée dès aujourd’hui. Les deux n’agissent sur une soumission que lorsque l’admission est appliquée (voir l’encadré plus haut).
Quand un fournisseur destinataire résiste
Le relais lit ce que répond chaque site destinataire, flux par flux, et peut retenir un flux vers un site pendant que ses autres sites continuent de recevoir. La décision se prend à la remise et tient en deux moitiés, chacune en ombre par défaut (décidée et enregistrée, rien n’est retenu) ou appliquée :google.com, outlook.com ou yahoodns.net) pour une heure, doublée si cela recommence dans la journée, six heures au plus. Trois choses déclenchent une pause :
- une des réponses de limitation de débit que publient Gmail, Microsoft et Yahoo : la première suffit ;
- 20 refus définitifs qui ne portent pas sur une adresse, en dix minutes ;
- 3 refus de réputation en une heure (chez Gmail, « likely unsolicited » et « very low reputation »). C’est le déclencheur qu’un flux lent peut atteindre : un seul refus de ce genre ne suspend rien, puisqu’un message peut le recevoir pour son seul contenu.
oximail account flow show liste les pauses d’un flux, et oximail account flow resume --site <site> en lève une.
L’allocation journalière. Un pool a un plafond journalier, dont 20 % sont réservés au courrier transactionnel. Chaque domaine de signature, et chaque adresse d’envoi, a une rampe vers chaque site : 500 destinataires par jour au départ, doublés tous les deux jours tant que les refus restent sous 2 %. Ce qui dépasse attend le lendemain, et un message de masse retenu au-delà de sa durée de vie est abandonné, l’abandon nommant l’allocation qui l’a retenu. Sur un serveur qui n’a aucun historique pour un domaine, lisez et réglez ses rampes avant la première grande campagne : oximail account relay ramp list et oximail account relay ramp set.
Appliquez pauses d’abord : ce réglage ne retient que ce qu’un site refuse déjà. Appliquez daily une fois qu’une campagne est passée en ombre et que oximail doctor a montré, sous relay_allowance, quelles rampes elle aurait épuisées.
Vérifier
Un
250 que reçoit votre plateforme après DATA signifie que le message survit à une coupure de courant (courrier et SMTP).
Relation avec les comptes relais
Si vous opérez un smarthost, notez la frontière : un compte relaisrole="service" a sa propre autorisation d’enveloppe (les domaines déclarés prouvés d’ADR-116) et ne peut pas recevoir de grants de domaine d’enveloppe. Un mécanisme par type de compte. Les grants sont pour les comptes normaux d’un Primary normal, qui envoient le courrier de listes de leur propre organisation. Les deux sortes de preuve sont des lignes du domaine du tenant : un tenant ne peut pas détenir une preuve sur le domaine d’un autre tenant.