SPF is one of those things that works silently until the day it doesn’t. A marketing team adds a new sending platform, someone pastes another include: into the record, and a week later a chunk of mail starts landing in spam for no obvious reason. Nine times out of ten the culprit is the same: the record grew past a limit almost nobody thinks about. This checker reads your record the way a receiving mail server does, follows every nested include, and tells you exactly where you stand.
What SPF actually authenticates
Sender Policy Framework is a published list, held in DNS, of the servers allowed to send mail for your domain. It’s defined by RFC 7208 (which obsoleted the original RFC 4408). When a receiving server accepts a connection, it takes the domain from the MAIL FROM command — the envelope sender, also called the Return-Path — looks up that domain’s SPF record, and checks whether the connecting IP is on the list.
Here’s the part that trips people up: SPF checks the envelope sender, not the From: address your recipients actually see. The two are often different — your email service provider frequently uses its own bounce domain in the envelope. That’s why SPF on its own does nothing to stop a spoofer putting your brand in the visible From: header. Closing that gap is the job of DMARC, which requires SPF (or DKIM) to align with the header domain. If you only remember one thing: SPF is necessary, but it is not sufficient.
The 10-lookup limit — the failure almost everyone eventually hits
Evaluating SPF can require DNS queries. The include, a, mx, ptr, exists and redirect mechanisms each cost at least one lookup, and RFC 7208 §4.6.4 caps the total at ten. Go over it and the result is PermError — a permanent error most receivers treat as an outright failure. Worse, a PermError means DMARC can no longer lean on SPF, so you’re suddenly relying on DKIM alone whether you planned to or not.
The trap is that the count is invisible from the outside. Your record might list four include: statements and look tidy, but each of those includes can pull in several more — a single provider’s include commonly expands to three or four netblock lookups. That’s how a record that “only has four includes” quietly consumes eleven lookups. This tool follows every branch and shows the running total; the SPF Include Tree visualises exactly which provider is eating your budget. There’s a second, quieter limit too: at most two void lookups (mechanisms that resolve to nothing), which usually point to a typo or a sender you decommissioned and forgot to remove.
How a receiver reads the record
Mechanisms are evaluated left to right, and the first match wins. Each mechanism carries a qualifier that decides the outcome when it matches:
+(the default) → Pass-→ Fail (hard fail — reject anything not listed)~→ SoftFail (accept but mark as suspicious)?→ Neutral (no opinion)
The record almost always ends with an all mechanism that catches everything not matched above. -all is the strict, correct end state; ~all is the sensible place to start a rollout while you confirm every legitimate sender is covered; and +all is a self-inflicted wound — it tells the world that any server on earth may send as you. Never publish it.
SPF and forwarding: the honest limitation
SPF breaks on plain forwarding. When a mailing list or a “forward my mail to Gmail” rule relays your message, the forwarding server becomes the new connecting IP — and that IP isn’t in your SPF record, so SPF fails at the final destination. This isn’t a bug you can fix in your record; it’s inherent to how SPF works. It’s also precisely why DKIM exists and why DMARC accepts either aligned SPF or aligned DKIM: a DKIM signature travels with the message and survives the trip. If deliverability matters to you, treat SPF and DKIM as a pair, not a choice.
The failure modes worth knowing
- Too many lookups → PermError. The big one. Consolidate, remove unused senders, or split senders across subdomains.
- More than one SPF record on the same name → PermError. A domain must publish exactly one
v=spf1record. Two “valid” records is an instant failure. - A stray
+allor a bare+qualifier. Anyone can now pass as you. - The
ptrmechanism. Deprecated by RFC 7208, slow, and unreliable — remove it. - Silent growth. A provider adds a netblock to their own include and your record tips over 10 without you touching it. Re-check after any sending change.
Worked examples
A clean, minimal record — one provider, soft-fail while you settle in:
v=spf1 include:_spf.google.com ~allHeading for a lookup-limit failure — every include counts, and this stack blows past ten once each one expands:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:sendgrid.net \ include:spf.protection.outlook.com include:amazonses.com include:mailgun.org \ include:_spf.salesforce.com include:spf.mtasv.net -all ← PermError riskDo not publish this — the classic own-goal:
v=spf1 +allHow to fix a lookup-limit failure (the right way)
Your record needs more than ten DNS lookups, so evaluation can return PermError. Work through these in order:
- Remove services you no longer send through. Old CRMs and abandoned newsletter tools are the usual dead weight.
- Consolidate overlapping includes. Some providers publish a single combined include that replaces several.
- Delegate to subdomains. Send marketing from
news.example.comand transactional frommail.example.com, each with its own small SPF record, so no single domain has to authorise everyone. - Publish direct
ip4:/ip6:ranges where a provider’s IPs are stable — a literal range costs zero lookups.
A word on “SPF flattening”: some tools rewrite all your includes into a flat list of IPs to dodge the limit. It works, but it’s a maintenance liability — the moment a provider changes its sending IPs, your flattened record is silently wrong and mail fails. If you flatten, monitor it. And whatever you do, never publish a second SPF record to make room — edit the one existing TXT record. When you’re done, re-run this checker and confirm the count is ten or fewer.
Where SPF sits in the bigger picture
SPF is one leg of a three-legged stool. Pair it with a valid DKIM signature, enforce both with a DMARC policy, and you have real protection against spoofing and a real shot at the inbox. To see how the three fit together for your domain in one view, run the Email Health Check; to confirm what your actual messages do (including whether SPF aligns with your From: domain in practice), send one through the Outbound Deliverability Test. Google and Microsoft both spell out their expectations for senders in their postmaster guidance (Google, Microsoft), and the anti-abuse working group M3AAWG publishes the industry best-practice documents most large mailbox providers follow.
Frequently asked questions
- Can a domain have more than one SPF record?
- No. Publish exactly one
v=spf1TXT record — two or more cause a PermError. Merge everything into one record. - Why does SPF pass but DMARC still fail?
- DMARC needs alignment: the domain that passed SPF (the Return-Path /
MAIL FROM) must match your visibleFrom:. Many ESPs use their own bounce domain, so SPF passes but isn’t aligned. Aligning DKIM usually fixes it. - What is a “void lookup”?
- A mechanism whose DNS query returns nothing. SPF allows at most 2 void lookups before PermError — usually a typo or a retired sender. The SPF Include Tree shows where they are.
- Should I use -all or ~all?
- Start with
~allwhile you confirm every sender is listed, then move to-allonce your DMARC reports are clean. - Does SPF survive email forwarding?
- Often not — the forwarder becomes the new sending IP, which isn’t in your SPF, so SPF fails downstream. DKIM survives forwarding, which is why DMARC accepts either aligned SPF or aligned DKIM.
- I use a lot of senders — how do I stay under 10 lookups?
- Split senders across subdomains, drop unused services, consolidate includes, and use direct
ip4/ip6ranges where IPs are stable. Flattening works but needs monitoring — provider IPs change.