בס״ד

SPF Record Checker

An SPF record is a TXT record listing the mail servers allowed to send as your domain, and RFC 7208 limits it to 10 DNS lookups. Our SPF checker reads the record, expands every include, redirect, a, mx and ptr mechanism, and counts the lookups, because going over 10 makes the record return permerror and every SPF check fail.

$ curl "https://api.dnsx.dev/email/spf/example.com?tree=1" # full expansion with lookup counts
$ curl https://api.dnsx.dev/email/spf/example.com # parsed top-level record

What is an SPF record?

An SPF record (Sender Policy Framework) is a TXT record published at the domain name itself, starting with v=spf1, that lists which mail servers may send email using that domain in the envelope sender (the MAIL FROM address, also called the return path). A receiving server reads the record during the SMTP session and compares the connecting IP address against it. The result is one of pass, fail, softfail, neutral, none, temperror or permerror. SPF is specified in RFC 7208, which replaced the experimental RFC 4408 in 2014.

SPF checks the envelope sender and never looks at the From header a person sees, which is why DMARC exists to tie the two together. It is also why forwarded mail fails SPF: the forwarder's server is not in the original domain's record.

example.com.  3600  IN  TXT  "v=spf1 include:_spf.google.com ip4:203.0.113.0/24 -all"
                                  │                       │                 │
                             one lookup              no lookup      unlisted senders fail

How is the SPF 10 lookup limit counted?

RFC 7208 section 4.6.4 caps one SPF evaluation at 10 terms that need a DNS query. The terms that count are include, a, mx, ptr and exists, plus the redirect modifier. Each include costs one lookup for its own TXT record and then adds every counting term inside the included record, so the total is recursive. A record with three includes that each contain two more includes has already spent nine lookups before its own a or mx terms are considered.

The ip4, ip6 and all terms cost nothing, because the receiver already has everything it needs to evaluate them. The exp modifier is also excluded from the count. Two further limits apply in the same section: an mx term may resolve at most 10 MX hosts, and the whole evaluation may hit at most 2 void lookups, meaning queries that come back with no record or NXDOMAIN. A third void lookup is a permerror on its own even when the total is well under 10.

Our tool shows the running count on every term in the expansion tree, so the first term marked over limit is the one that pushed the record past 10.

Why does an SPF record return permerror?

Permerror means the receiver could not evaluate the record at all. The three usual causes are more than 10 DNS lookups, more than 2 void lookups, and two TXT records on the domain that both start with v=spf1. Syntax mistakes cause it too: a mechanism with a typo, an include pointing at a domain with no SPF record, or a record split across quoted strings in the wrong place.

DMARC maps permerror to an SPF failure, so a domain whose record is over the limit passes DMARC only when DKIM passes and aligns. Any message that loses its DKIM signature in transit, which happens with mailing lists and some forwarders, then fails DMARC outright. Most domains get there gradually: each new vendor asks for one more include, and nobody counts.

How do I flatten an SPF record to fix too many lookups?

Flattening replaces an include with the ip4 and ip6 ranges it expands to. Those terms cost no lookups, so a record that was 14 lookups deep can come down to 2 or 3. The expansion tree on this page lists the ranges collected under every include, and the authorised ranges card gathers all of them for the whole record.

  1. Remove includes for services the domain no longer sends from. Old vendors are the most common waste.
  2. Flatten includes whose ranges rarely change, such as your own mail servers or a small provider.
  3. Keep the include for large providers such as Google and Microsoft, which change their ranges often. A flattened copy goes stale and then rejects real mail.
  4. Move bulk senders to their own subdomain, such as news.example.com, with a separate SPF record and DKIM key. DMARC alignment still works in relaxed mode.
  5. Drop ptr entirely. RFC 7208 says receivers should not rely on it, and it costs a lookup for nothing.

Automated flattening services keep the ranges current, at the cost of putting a third party in control of a security record. Fewer senders is the better fix.

What is the difference between ~all, -all and ?all?

The all mechanism matches every sender, so it goes last and its qualifier decides what happens to a server that matched nothing before it. -all returns fail: the message is not authorised and the receiver may refuse it. ~all returns softfail: the message is probably not authorised, and the receiver should accept it and mark it. ?all returns neutral, which is the same as publishing no record at all. +all returns pass for everyone, which authorises the entire internet and is a mistake.

Google's guidance for Workspace ends the record in ~all, and Microsoft's for 365 ends it in -all. Both are fine once DMARC is in place, because DMARC only accepts an SPF pass as a pass and its policy then decides the outcome. Without DMARC, -all is the stricter choice and ~all the safer one while you are still finding out which services send as your domain.

What SPF record do Google Workspace and Microsoft 365 need?

ProviderRecord to publishLookups
Google Workspacev=spf1 include:_spf.google.com ~all1
Microsoft 365v=spf1 include:spf.protection.outlook.com -all1
Both, plus your own serverv=spf1 include:_spf.google.com include:spf.protection.outlook.com ip4:203.0.113.10 -all2
A domain that never sends mailv=spf1 -all0

Each provider publishes one include that fans out internally, so check the tree rather than assuming it costs one lookup. Every additional service (a helpdesk, a CRM, a newsletter tool) adds at least one more, and the total creeps toward 10 faster than most people expect.

How do I check an SPF record on Windows?

Open Command Prompt or PowerShell. nslookup ships with every version of Windows, and Resolve-DnsName is the PowerShell cmdlet. Query the TXT records of the domain and look for the string starting with v=spf1, then follow an include by querying the included domain the same way.

nslookup -type=TXT example.com
Resolve-DnsName -Type TXT example.com
Resolve-DnsName -Type TXT _spf.google.com

How do I check an SPF record on macOS?

macOS ships dig, so no install is needed. The +short form prints only the record values. Look for the string starting with v=spf1, and follow an include by querying the TXT record of the included domain in the same way.

$ dig TXT example.com +short
"v=spf1 include:_spf.google.com -all"

$ dig TXT _spf.google.com +short
"v=spf1 ip4:74.125.0.0/16 ip4:209.85.128.0/17 ... ~all"

How do I check an SPF record on Linux?

dig and host come from the dnsutils package on Debian and Ubuntu and from bind-utils on Fedora and RHEL. The +noall +answer options print only the answer section with the TTL, which tells you how long a resolver will keep serving an old record after you change it.

dig TXT example.com +noall +answer
dig TXT _spf.google.com +short
host -t TXT example.com

Frequently Asked Questions

What is an SPF record?
An SPF record is a TXT record on a domain that starts with v=spf1 and lists the mail servers allowed to send email using that domain in the envelope sender. Receiving servers look it up during delivery and compare the connecting IP address against it. SPF is defined in RFC 7208.
How many DNS lookups can an SPF record have?
Ten. RFC 7208 section 4.6.4 limits an SPF evaluation to 10 DNS-querying terms: include, a, mx, ptr, exists and the redirect modifier. Nested includes count too. The ip4, ip6 and all terms cost nothing. A separate limit allows at most 2 void lookups, which are queries that return no record or NXDOMAIN. DNSX counts both and shows which term crosses the line.
What does SPF permerror mean?
Permerror is the SPF result for a record that cannot be evaluated: it exceeds 10 DNS lookups, has a syntax error, or the domain publishes two SPF records. Receivers treat a permerror as a failed check, and DMARC treats it as an SPF failure, so the domain then depends entirely on DKIM to pass DMARC.
What is the difference between ~all and -all in SPF?
Both end the record and apply to any server not listed before them. -all is a hard fail, telling receivers the message is not authorised. ~all is a soft fail, telling receivers the message is probably not authorised and should be marked rather than refused. Once DMARC is enforced the difference matters little, because DMARC only counts an SPF pass as a pass.
How do I fix "too many DNS lookups" in SPF?
Remove includes for services you no longer send from, replace includes for services with stable addresses with their ip4 and ip6 ranges (called flattening), and move marketing or transactional senders to a subdomain with its own SPF record. DNSX shows the full expansion tree with the lookup number on each term, so you can see which include costs the most.
Can a domain have two SPF records?
No. RFC 7208 section 3.2 says a domain with more than one TXT record starting with v=spf1 produces a permerror, and every SPF check on that domain fails. Merge the two records into one. A domain can still have other TXT records, such as site verification strings, without any conflict.

Related tools