Dr.Who
← blog

SPF results explained: pass, fail, softfail, neutral, none, temperror, permerror

· spf · email · dmarc · deliverability · dns

spfemaildmarcdeliverabilitydns

When a receiving server evaluates SPF it returns exactly one of seven results: pass, fail, softfail, neutral, none, temperror, or permerror. pass means the sending IP is authorized by your SPF record; the four "not pass" results (fail, softfail, neutral, none) mean it is not authorized or you have no opinion; the two *error results mean the check could not complete. Only a pass can produce SPF alignment for DMARC — everything else leans toward a DMARC failure unless DKIM carries the message.

The seven results, defined

  • pass — the sending IP matched a mechanism in your record (an ip4, ip6, a, mx, or include). The mail is SPF-authenticated.
  • fail (hardfail) — the IP is not authorized and your record ends in -all. This is an explicit "reject this." Many receivers will refuse or junk it.
  • softfail — the IP is not authorized and your record ends in ~all. A weak "probably not us." Receivers usually accept but mark it down.
  • neutral — your record ends in ?all. You are explicitly stating no opinion. Treated almost identically to having no record.
  • none — no SPF record is published at all (or the lookup returned nothing). The receiver learns nothing.
  • permerror — a permanent error: a syntax mistake, more than one SPF record, or exceeding the 10 DNS-lookup limit. The record is unusable.
  • temperror — a transient error, almost always a DNS timeout or SERVFAIL. Retry and it may resolve to something else.

What the qualifier letter means

The "not pass" result is driven by the qualifier on the all mechanism that closes your record:

  • -allfail (hardfail)
  • ~allsoftfail
  • ?allneutral
  • +allpass for everyone — never publish this; it authorizes the entire internet to send as you.

So v=spf1 include:_spf.google.com ~all returns softfail for any IP Google's include doesn't cover. Swap the tail for -all and the same unauthorized IP now returns fail.

How DMARC treats each result

DMARC alignment only fires on an SPF pass where the authenticated domain matches your From: domain. So fail, softfail, neutral, and none all count the same to DMARC — none produce SPF alignment, and the message must be rescued by aligned DKIM or it fails DMARC outright. The qualifier you chose (-all vs ~all vs ?all) changes how non-DMARC receivers treat the raw result, not the DMARC outcome. temperror is usually evaluated as if SPF were unavailable, and a receiver may defer the message.

Which qualifier to actually publish

  • -all (hardfail) — the right answer once you have inventoried every legitimate sender and confirmed they all pass. This is the only qualifier that meaningfully blocks spoofing at SPF time.
  • ~all (softfail) — the safe transition state. Publish it while you watch DMARC aggregate reports and confirm no legitimate stream is failing, then tighten to -all.
  • ?all (neutral) — effectively pointless. It is no better than publishing nothing; skip it.
  • +all — actively harmful. Authorizes the world. There is no legitimate use.

If you are seeing permerror in reports, the cause is almost always the 10 DNS-lookup cap — too many include chains. Flatten or trim them before tightening your qualifier.

Run the check on your domain →

Further reading