SPF : trop de requêtes DNS, corriger le permerror des 10 lookups
Pourquoi SPF renvoie permerror au-delà de 10 requêtes DNS, quels mécanismes comptent, comment compter votre enregistrement, et les corrections durables.
Publié: · 8 min de lecture
Un enregistrement SPF ne peut déclencher l'évaluation que de dix termes nécessitant une requête DNS au plus par vérification. include, a, mx, exists, redirect et ptr comptent, et tout ce qui se trouve dans les include imbriqués compte aussi. ip4, ip6 et all ne coûtent rien. La onzième requête met fin à l'évaluation avec un permerror, et un permerror n'est pas un pass : du point de vue de DMARC, SPF n'a tout simplement pas réussi. La correction durable consiste à avoir moins de services dans l'enregistrement, pas à les dissimuler plus habilement.
La règle vient de la RFC 7208, section 4.6.4.
Ce qui compte et ce qui ne compte pas
| Terme | Compte dans les 10 ? | Remarque |
|---|---|---|
include: |
Oui | Plus chaque terme comptabilisé à l'intérieur de l'enregistrement inclus, récursivement |
a |
Oui | Également a:host.example.com |
mx |
Oui | Possède en plus une limite propre, voir ci-dessous |
exists: |
Oui | Surtout utilisé avec des macros |
redirect= |
Oui | Un modificateur, mais il déclenche une requête |
ptr |
Oui | Déconseillé par la RFC elle-même ; retirez-le |
ip4:, ip6: |
Non | Adresses littérales, aucun DNS nécessaire |
all |
Non | |
exp= |
Non | Récupéré seulement pour composer un texte d'explication après un échec |
La limite s'applique à une évaluation SPF dans son ensemble. La récupération initiale de votre propre enregistrement TXT n'est pas comptée ; tout ce que cet enregistrement déclenche ensuite l'est.
Deux autres limites dans la même section
- Éclatement de
mxetptr. L'évaluation d'un mécanismemxne doit pas conduire à plus de dix recherches d'adresses pour les noms MX qu'il renvoie (le même plafond s'applique aux noms trouvés parptr). Un domaine qui a plus de dix hôtes MX produit un permerror par cette porte, même si le nombre total de termes est faible. - Requêtes vides (void lookups). Une requête qui renvoie NXDOMAIN ou une réponse vide est une « requête vide ». La RFC indique que les destinataires DEVRAIENT n'en tolérer que deux par évaluation et renvoyer permerror au-delà. Deux include morts, laissés par des services résiliés, peuvent suffire.
Et un classique qui n'a rien à voir avec le comptage
Deux enregistrements TXT commençant par v=spf1 sur le même nom donnent également un permerror. Cela arrive quand le guide d'un nouveau prestataire dit « ajoutez cet enregistrement SPF » et que quelqu'un fait exactement cela. Fusionnez les mécanismes en un seul enregistrement.
Pourquoi les échecs semblent intermittents
Permerror signifie « cet enregistrement ne peut pas être interprété ». Ce que le destinataire en fait relève de sa politique locale : certains le traitent comme un fail, d'autres comme un neutral. DMARC ne se demande qu'une chose : SPF a-t-il produit un pass aligné ? Et un permerror n'est pas un pass. Si votre courrier porte aussi une signature DKIM alignée, DMARC passe quand même, et personne ne remarque l'enregistrement SPF cassé pendant des mois. Puis un message sans DKIM (un serveur applicatif oublié, un scanner) se met à rebondir chez un fournisseur et à arriver chez un autre.
L'ordre des mécanismes ajoute à la confusion. SPF évalue de gauche à droite et s'arrête à la première correspondance. Un expéditeur qui correspond à votre deuxième mécanisme n'atteint jamais la onzième requête ; un expéditeur listé en fin d'enregistrement, si. Le même enregistrement peut donc passer pour votre fournisseur de messagerie et produire un permerror pour votre outil de facturation.
Comptez votre enregistrement à la main
Partez de l'enregistrement lui-même :
$ dig +short TXT example.com | grep spf1
"v=spf1 mx a include:_spf.mailprovider.example include:spf.newsletter.example include:spf.crm.example include:spf.helpdesk.example ip4:192.0.2.10 -all"
Suivez ensuite chaque include, et chaque include à l'intérieur de ceux-ci :
$ dig +short TXT _spf.mailprovider.example
"v=spf1 include:_netblocks1.mailprovider.example include:_netblocks2.mailprovider.example include:_netblocks3.mailprovider.example ~all"
$ dig +short TXT _netblocks1.mailprovider.example
"v=spf1 ip4:198.51.100.0/24 ip6:2001:db8:10::/48 ~all"
Notez une ligne par terme comptabilisé :
Terme dans example.com |
Coût propre | Coût imbriqué | Sous-total |
|---|---|---|---|
mx |
1 | 0 | 1 |
a |
1 | 0 | 1 |
include:_spf.mailprovider.example |
1 | 3 include | 4 |
include:spf.newsletter.example |
1 | 1 include | 2 |
include:spf.crm.example |
1 | 1 include + 1 a |
3 |
include:spf.helpdesk.example |
1 | 0 | 1 |
ip4:192.0.2.10 |
0 | 0 | 0 |
| Total | 12 |
Douze : permerror pour tout expéditeur qui n'est pas reconnu tôt dans l'enregistrement. Notez que le all situé dans un enregistrement inclus ne met pas fin à votre évaluation ; un include n'a d'effet que lorsqu'il produit un pass.
Les corrections, dans l'ordre où les essayer
1. Retirez ce que vous n'utilisez plus
La plupart des enregistrements qui dépassent la limite contiennent au moins un service résilié depuis des années. Chaque prestataire retiré libère en général une à quatre requêtes. Cela referme aussi une brèche : un include autorise les adresses d'envoi de la plateforme pour votre domaine, et sur une infrastructure partagée ces adresses transportent aussi le courrier d'autres clients.
2. Remplacez a et mx par des adresses
mx et a sont des valeurs par défaut commodes que beaucoup de générateurs ajoutent. Si votre serveur web n'envoie pas de courrier, a ne sert à rien. Si les hôtes de vos enregistrements MX n'envoient pas votre courrier sortant (le cas habituel avec une messagerie hébergée, où l'include du fournisseur couvre l'envoi), mx ne sert à rien non plus. Là où un serveur envoie réellement et où son adresse est stable, écrivez ip4:192.0.2.10 ou ip6:2001:db8::25 à la place : zéro requête.
3. Vérifiez si le service utilise seulement votre domaine dans l'enveloppe
SPF contrôle le domaine de l'expéditeur d'enveloppe (MAIL FROM, affiché ensuite comme Return-Path), pas l'en-tête From que voient les gens. Beaucoup de prestataires d'e-mailing y placent leur propre domaine de rebond. Dans ce cas, le destinataire consulte leur enregistrement SPF, jamais le vôtre, et leur include dans votre enregistrement coûte des requêtes sans rien faire.
Ouvrez un message réellement envoyé par le service et lisez les en-têtes :
Return-Path: <bounce-7f3a@bounces.newsletter.example>
From: Example Shop <news@example.com>
Return-Path n'est pas sous example.com : include:spf.newsletter.example peut donc quitter votre enregistrement d'apex. Ce qui fait passer ce courrier à DMARC, c'est une signature DKIM avec d=example.com, ou un return-path personnalisé (étape suivante).
4. Donnez à chaque service d'envoi son propre sous-domaine
La limite vaut par évaluation, et chaque évaluation part du domaine d'enveloppe. Envoyez les newsletters depuis news.example.com et le courrier transactionnel depuis billing.example.com, et chaque nom dispose de son propre enregistrement et de son propre budget de dix :
news.example.com. TXT "v=spf1 include:spf.newsletter.example -all"
billing.example.com. TXT "v=spf1 include:spf.invoicing.example -all"
La plupart des plateformes proposent cela sous le nom de « return-path personnalisé » ou « domaine de rebond personnalisé » : vous créez un CNAME tel que bounce.news.example.com pointant vers le prestataire, et l'enregistrement SPF vit entièrement de leur côté. En alignement souple (le mode par défaut de DMARC), bounce.news.example.com est aligné avec une adresse From en example.com. Les enregistrements SPF ne s'héritent pas : un sous-domaine sans enregistrement propre n'en a aucun.
5. Appuyez-vous sur un DKIM aligné
DMARC a besoin d'un seul pass aligné, SPF ou DKIM. Pour chaque service capable de signer avec votre domaine dans d=, DKIM seul suffit, et il survit au transfert, ce que SPF ne fait pas (voir pourquoi le transfert d'e-mails casse SPF). C'est ce qui rend l'étape 3 sûre.
6. L'aplatissement, seulement avec de l'automatisation
L'« aplatissement » (flattening) remplace chaque include par les plages d'adresses IP vers lesquelles il se résout aujourd'hui. Le nombre de requêtes tombe à zéro et l'enregistrement fonctionne le jour même. Le problème, c'est le lendemain : les fournisseurs ajoutent et retirent des plages sans vous prévenir, et le jour où ils le font, une partie de votre courrier légitime se met à échouer à SPF avec un enregistrement qui paraît parfaitement valide. Si vous aplatissez, il faut un processus qui re-résout régulièrement les include et republie l'enregistrement, et il faut surveiller ce processus. Un enregistrement aplati à la main est une panne différée.
Les enregistrements aplatis deviennent aussi longs. Une chaîne de caractères TXT contient au plus 255 octets ; les enregistrements plus longs sont découpés en plusieurs chaînes, que les destinataires concatènent sans ajouter d'espace, si bien qu'une coupure au mauvais endroit colle deux mécanismes ensemble. Gardez également la réponse complète petite : au-delà de la taille UDP traditionnelle de 512 octets, les réponses dépendent d'EDNS0 ou d'un repli sur TCP, et la RFC conseille de rester en dessous.
7. Les macros
Les macros SPF (exists:%{i}._spf.example.com) peuvent replier de nombreux expéditeurs en une seule requête. Elles exigent un backend DNS conçu pour cela et sont difficiles à déboguer : ce n'est pas une correction de première intention.
~all contre -all n'a aucun rapport avec tout cela : le qualificateur de all décide du sort des expéditeurs qui ne correspondent à rien, et ne coûte aucune requête dans un cas comme dans l'autre.
Erreurs fréquentes
- Ne compter que les include visibles dans l'enregistrement de premier niveau et oublier ceux qui sont imbriqués.
- Ajouter un
include:pour un service dont le Return-Path est sur son propre domaine. - Laisser en place les include de services résiliés : ils coûtent des requêtes et, une fois que le prestataire supprime le nom, des requêtes vides.
- Publier un second enregistrement
v=spf1au lieu de modifier le premier. - Découper un enregistrement long en chaînes de 255 octets et perdre l'espace entre deux mécanismes à la jonction.
Si vous construisez un enregistrement à partir de zéro, le générateur SPF assemble la syntaxe ; le comptage, lui, doit toujours se faire contre les include réels.
Vérifiez avec OrbitProbe
Le vérificateur SPF d'OrbitProbe recherche l'enregistrement SPF d'un domaine et signale les problèmes qui le cassent le plus souvent : plusieurs enregistrements, +all, un mécanisme all manquant et un trop grand nombre de requêtes DNS. Lancez-le pour le domaine apex, puis séparément pour chaque sous-domaine qui envoie du courrier, car chaque nom est évalué pour lui-même. Une recherche DNS montre ce qui est publié à cet instant ; elle ne peut pas montrer si votre courrier est accepté, alors continuez de lire vos rapports DMARC. Pour la vue d'ensemble des dépendances entre les quatre enregistrements de messagerie, voyez MX, SPF, DKIM et DMARC expliqués, et pour une revue complète de la livraison, la liste de contrôle DNS pour les e-mails qui arrivent en spam.