How to fix an SPF permerror

· 4 min read

A permerror is the worst SPF state a domain can be in: the record exists, but receivers cannot evaluate it and behave as if it were absent. Mail lands in spam although "SPF is set up". The causes are almost always the same five.

What permerror means

RFC 7208 defines seven SPF results: none, neutral, pass, fail, softfail, temperror and permerror. A permerror (permanent error) says the record is constructed in a way that makes correct evaluation impossible. Unlike a temperror, retrying does not help; the fault is in the zone itself.

How a receiver handles it is entirely up to the receiver. In practice Google and Microsoft treat permerror like "no SPF": the message gets no authentication credit, and if DMARC depends on SPF, DMARC fails as well. That is why a permerror is worse than a missing record: you believe you are protected, but you are not.

Cause 1: More than ten DNS lookups

By far the most common cause. A receiver may perform at most ten DNS queries while evaluating the record. Every include, a, mx, ptr, exists and redirect counts, including the lookups that the included records themselves trigger. Microsoft 365 costs two, Google Workspace three, a typical newsletter tool two to four. Add a CRM, a ticket system and the old hosting provider, and the limit is gone.

The fix is cleaning up, not tricks: remove services that no longer send. Replace includes of services with fixed IP addresses by ip4 or ip6 mechanisms, which cost no lookup. If that is not enough, spread senders across subdomains (newsletter.example.com with its own SPF), because every domain has its own limit.

v=spf1 include:spf.protection.outlook.com include:_spf.google.com include:sendgrid.net include:mail.zendesk.com include:servers.mcsv.net include:spf.old-host.example -all

Result: 13 lookups, permerror. After cleaning up:

v=spf1 include:spf.protection.outlook.com include:sendgrid.net ip4:203.0.113.10 -all

Cause 2: Multiple SPF records

A domain may have exactly one TXT record starting with v=spf1. Two of them are a permerror by RFC, regardless of content. This happens when a provider's guide says "add this TXT record" and the client takes it literally instead of extending the existing record.

Check all TXT records of the domain and merge every mechanism into a single record. Delete the rest.

Cause 3: Syntax errors

One typo is enough. Typical cases: "include=" instead of "include:", a space inside a mechanism, "v=spf1" not at the start, a line break or quotation mark in the middle of the record because the DNS editor split a long string, or a mechanism that does not exist ("ipv4:" instead of "ip4:").

Strings longer than 255 characters are especially tricky: DNS only allows them as several sub-strings that the receiver joins again. Some DNS panels split them in the wrong place, leaving a quotation mark in the middle of a domain name.

  • Every mechanism with a colon: include:, ip4:, ip6:, a:, mx:, exists:
  • Exactly one space between mechanisms, no tabs, no commas
  • The all term exactly once and at the very end
  • Upper case is not required, but it does no harm either

Cause 4: Include pointing to a domain without SPF

include:spf.service.example only works if spf.service.example has an SPF record itself. If it is missing because the service moved, changed its hostname or the client mistyped it, the whole domain gets a permerror. One orphaned include is enough.

The SPF checker resolves every include and shows which targets return no record. Remove such entries or replace them with the current hostname from the provider's documentation.

Cause 5: Redirect loops and ptr

Rarer, but stubborn: a redirect= pointing to a domain that points back, or an include that eventually includes itself. The receiver aborts and reports permerror. The obsolete ptr mechanism does not cause a permerror, but many receivers ignore it and it costs lookups; remove it.

Step by step

The order matters, because one error can hide the next.

  1. Fetch all TXT records of the domain and make sure exactly one starts with v=spf1.
  2. Run the record through the SPF checker: syntax, lookup count and orphaned includes are shown.
  3. Remove services that no longer send. If unsure, ask the client which systems sent mail in the last twelve months.
  4. Switch static senders to ip4/ip6, move bulk senders to subdomains.
  5. Publish the new record with -all or, for now, ~all, keep the TTL short and re-check after five minutes.
  6. Watch the DMARC reports of the following days: they show whether all legitimate senders now pass.

Frequently asked questions

Can I get around the lookup limit with SPF flattening?
Flattening replaces all includes with the resolved IP addresses. It works until a provider changes its addresses, which Microsoft and Google do regularly. Without automation, flattening is a ticking time bomb. Cleaning up is almost always the better solution.
How long until the fixed record takes effect?
As long as the TTL of the old record, usually between five minutes and one hour. Receivers do not cache SPF beyond that.
Why does one tool show permerror and another pass?
Some tools count lookups differently or ignore syntax errors. What matters is the behaviour of large receivers, and they follow RFC 7208 strictly. When in doubt, look at the DMARC aggregate reports from Google.
Check now

Free SPF record check and lookup: syntax, includes, the 10 DNS lookup limit and the closing qualifier. Shows whether your domain blocks forged senders.

SPF records change because providers move and clients add entries. DomainWarn checks SPF, DKIM and DMARC of all client domains regularly and tells you as soon as a record breaks.

Monitor this domain continuously14-day free trial, no credit card.

More guides