Skip to content

SPF Checker

An SPF checker reads the v=spf1 TXT record a domain publishes, parses every mechanism, and counts the DNS lookups the record really costs once each include is followed. It tells you whether receivers will return Pass, SoftFail, Fail, or the PermError that silently breaks authentication.

What SPF actually authorises

Sender Policy Framework (RFC 7208) is a list of the hosts allowed to send mail for a domain. The critical detail almost everyone gets wrong: SPF authorises the envelope sender, the address in the SMTP MAIL FROM command, not the From: header your recipient sees. A message can pass SPF perfectly while showing a completely forged From: address, which is exactly why DMARC exists — DMARC is the layer that ties the authenticated envelope domain back to the visible header domain.

When a receiving mail server accepts a connection it takes the envelope sender domain, queries that domain for TXT records, and finds the one beginning v=spf1. It then walks the mechanisms left to right, stopping at the first one that matches the connecting IP address. The qualifier on that mechanism becomes the result: + Pass, - Fail, ~ SoftFail, ? Neutral. If nothing matches before the terminating all, the qualifier on all decides. That left-to-right, first-match-wins evaluation is why the order of your mechanisms matters and why anything after all is dead code.

The 10-lookup limit and PermError

RFC 7208 §4.6.4 caps the number of DNS-querying terms an SPF evaluation may use at ten. The terms that spend from that budget are include, a, mx, ptr, exists, and the redirect modifier. The terms that cost nothing are ip4, ip6, all, and exp. The limit is not per record — it is per evaluation, counted across the whole tree. If your record contains three includes and each of those provider records contains three includes of its own, you have spent twelve lookups, not three.

Exceeding ten lookups does not produce a SoftFail or a "mostly working" state. A compliant receiver must return PermError, and Gmail, Outlook, and Yahoo all treat PermError as an SPF failure. If your only DMARC-aligned authentication was SPF, every message you send starts failing DMARC the moment you cross the line.
Read the full explanation of spf checker results ↓

The failure mode is nasty because it is invisible from your side. You add one more SaaS tool — a helpdesk, an invoicing app, a newsletter platform — the vendor tells you to append one include:, and nothing appears to break. Your own test messages still arrive because they match an earlier mechanism. But receivers that evaluate the whole record hit the eleventh lookup, abort, and return PermError. Bounces start arriving from a subset of recipients days later, and the change that caused it is long forgotten.

A second, separate limit catches people out too: the mx and ptr mechanisms may each trigger at most ten address lookups internally, and a "void lookup" limit of two applies to queries that return NXDOMAIN or an empty answer. A stale include: pointing at a decommissioned vendor domain burns a void lookup and, once the target has no SPF record at all, is itself a PermError.

How to read the results above

What you seeWhat it meansWhat to do
Green counter, -allRecord is inside budget and hardfails unlisted senders.Nothing. This is the target state.
Amber counter (8–10)One more provider will break the record.Replace include: entries for your own servers with ip4: before adding anything else.
Red counter (>10)PermError. SPF is failing for every message right now.Remove unused includes, consolidate providers, or flatten. Fix today.
?all or no allNeutral — receivers learn nothing they did not already know.Change to ~all, then -all once the sender list is complete.
+allEvery host on the internet passes SPF for your domain.Remove it immediately. This is worse than having no SPF record.
Two v=spf1 recordsPermError before a single mechanism is evaluated.Merge them into one TXT record and delete the other.

The mechanism table shows each term with the result it produces on a match and whether it spends a lookup. Work down it and ask, for every lookup-consuming term, "does this still send mail for us?" Most over-budget records are 60% dead weight — a former ESP, a CRM that was trialled and dropped, a hosting provider from two migrations ago.

The five failures that actually happen

  1. Two SPF records. A migration adds a new record instead of editing the old one. RFC 7208 §4.5 requires exactly one; two means PermError for everything. Check with a full TXT lookup, not just an SPF tool.
  2. Over ten lookups. The single most common cause of "email suddenly stopped authenticating". See the PermError guide for the flattening options and their trade-offs.
  3. A record on the wrong name. SPF belongs on the bare domain (@), not on spf.example.com or _spf.example.com. Those names are only ever include targets.
  4. `-all` published before the sender list was complete. Invoicing systems, monitoring alerts, and the CRM nobody remembers all start hardfailing. Publish ~all first and read your DMARC aggregate reports for a month.
  5. A record longer than 255 characters not split correctly. A single TXT string is capped at 255 bytes; longer records must be published as multiple quoted strings inside one TXT record, which concatenate with no separator. A panel that inserts a space between chunks corrupts the record.

If you need to cut lookups, the order of preference is: delete includes for services you no longer use; replace include: with the literal ip4: ranges when a provider publishes a small, stable set; drop a and mx if your mail server IPs are already covered by an ip4:; and only then consider automated flattening. Flattening — expanding every include into literal IPs — works, but it makes you responsible for tracking a provider's IP changes forever. When Google or Microsoft renumbers, your mail fails and no one tells you.

Check it from the command line

Every result on this page is reproducible with dig. Query the domain for TXT and pick the record that starts with v=spf1:

# The domain's own SPF record
dig +short TXT example.com | grep spf1

# Follow an include by hand to see what it costs
dig +short TXT _spf.google.com

# Query a specific resolver to rule out local caching
dig @8.8.8.8 +short TXT example.com

# Full answer with TTL, so you know how long a fix takes to propagate
dig TXT example.com +noall +answer
Reproduce the checker with dig — the SPF record is just a TXT record.

To count lookups by hand, run the first command, note every include:, a, mx, ptr, and exists term, then run dig +short TXT against each include target and repeat. The total across the whole tree is your lookup count. That manual walk is exactly what the checker above automates.

SPF is one third of the job

SPF breaks on forwarding: when a recipient auto-forwards your message, the forwarding server connects from its own IP with your envelope domain, and SPF fails. DKIM survives forwarding because it signs the message itself, which is why DMARC accepts either aligned SPF or aligned DKIM. A domain with a perfect SPF record and no DKIM is one mailing list away from failing DMARC. Verify all three, then confirm the policy with the DMARC checker.

SPF Record Generator
Build a correct SPF record with provider presets

Frequently asked questions

What is the difference between ~all and -all?
Both mark unlisted senders as unauthorised. ~all (SoftFail) tells receivers to accept the message but treat it as suspicious; -all (Fail) tells them to reject it. Under DMARC the practical difference is small, because a DMARC policy of quarantine or reject acts on the failure either way. Use ~all while you are still discovering senders, then move to -all. See the full comparison.
How many DNS lookups does my SPF record use?
Run the checker above — it counts recursively, following every include: and redirect= into the provider records and adding their lookup-consuming terms to the total. Counting only the terms visible in your own record will underestimate it badly; a single include: can hide three or four nested lookups.
Can I have two SPF records?
No. RFC 7208 §4.5 says a domain must publish exactly one v=spf1 record, and receivers that find two must return PermError — SPF then fails for every message, including the ones the records were meant to authorise. If two providers each gave you a record, merge their mechanisms into a single record with one all at the end.
Does SPF check the From: address my recipients see?
No. SPF validates the envelope sender (MAIL FROM, also called Return-Path), which recipients never see. A spammer can pass SPF for their own domain while putting your domain in the visible From: header. Only DMARC requires the two to align, which is why SPF alone does not stop spoofing.
Why did my SPF record start failing when I did not change it?
Almost always because a provider changed theirs. Your record includes theirs, so when they add an include of their own, your total lookup count rises past ten and receivers begin returning PermError. Re-run the check after any provider announcement, and keep two lookups of headroom.
Do subdomains inherit the parent domain SPF record?
No. SPF has no inheritance. Every subdomain that sends mail needs its own v=spf1 TXT record, and a subdomain with no record simply has no SPF policy. If a subdomain never sends mail, publish v=spf1 -all on it to make that explicit.
Should I flatten my SPF record?
Only as a last resort. Flattening replaces include: terms with the literal IP ranges behind them, which fixes the lookup count but transfers responsibility for tracking every provider IP change to you. If you flatten, automate the regeneration and monitor it — a stale flattened record fails silently and you find out through bounces.