Fixing SPF PermError and the DNS lookup limit
PermError means a receiving server could not evaluate your SPF record at all. It is not a soft warning: SPF contributes nothing to DMARC while it is happening, and you will not be told.
Why PermError happens
RFC 7208 allows at most ten DNS-resolving terms per evaluation. Each
include:, a, mx, ptr,
exists and redirect= costs one, and the count carries
down into every nested include. Cross the limit and evaluation stops and
returns permerror.
Two other things cause it, and they are easy to miss:
- More than one
v=spf1record on the domain. A receiver cannot choose between them, so it gives up. - More than two void lookups, meaning includes pointing at domains with no SPF record. This is independent of the ten lookup limit.
Common causes
- Several third-party platforms, each contributing an
include:with includes of its own. - Entries for services you stopped using, still costing lookups.
- Includes pointing at domains that no longer publish a record.
- One vendor whose record alone costs five or more.
A record like this is already close, and looks perfectly reasonable:
v=spf1 include:spf.marketing.com include:_spf.crm.com
include:mail.security.com include:_spf.support.com
include:email.gateway.com -all
Fix it properly first, if you can
Before reaching for any tool, two changes solve this permanently for a lot of domains:
- Remove what you no longer use. Check each include against a service you actually send from today.
- Split by subdomain. Marketing from
marketing.example.com, transactional mail fromalerts.example.com, each with its own short record. This is the cleanest answer and it never runs out of room.
SPF Guru exists for the cases where neither is possible, usually because a vendor insists on sending as your root domain.
What SPF Guru does
One term goes at the front, followed by the all your record
already ended with:
v=spf1 exists:i.%{ir}._d.%{d}.my.spf.guru ~all <your existing mechanisms>
It uses SPF macros: %{ir} expands to the connecting IP address
reversed, and %{d} to your domain. A receiving server resolves that
one name. If the sending IP is authorised, SPF Guru answers and the mechanism
matches, so evaluation stops with a pass. If it is not, there is no answer, the
mechanism does not match, and the next term is your own all. Either
way, one lookup, and the rest of your record is never walked by the receiver.
Everything after the all stays. Those
mechanisms are the input SPF Guru reads when it answers. A record stripped
down to just the guru include authorises nothing at all.
What other checkers will say
Your record still contains every original mechanism, so any tool that counts terms without evaluating them will still report you as over the limit. That is expected and it is not a fault in either tool. The number that decides whether your mail authenticates is what a receiving server actually performs, and that is one.
Trade-offs worth knowing
- Your SPF result depends on SPF Guru answering. If it does not, the
mechanism simply does not match and your own
alldecides, so unauthorised mail is still handled but authorised senders are no longer recognised. If one sender matters more than the others, its include can sit just after the guru term; see how it works. - Each unauthorised check spends one of the two void lookups RFC 7208 permits, because "no answer" is how the mechanism says no.
- This is a free, best-effort service with no uptime guarantee. Configure DKIM as well, so DMARC has a second way to pass. See the disclaimer.
Check where you stand
Enter your domain to see what your record costs today. If it is already within the limit, you will be told that and you can leave it alone. To test whether a specific server passes, use the SPF checker.
Support
Raise an issue at github.com/smck83/spf.guru/issues or email helpme@spf.guru. Volunteer, best-effort, no guaranteed response time.