The SPF record, explained
What each part of an SPF record does, how it ends, where the ten-lookup limit bites, and how SPF relates to DMARC.
By the TrustSek editorial team · Last reviewed
- Module
- Email security · 20%
- Scored on
- Presence, duplicates, all
- Lookup limit
- 10 per evaluation
SPF is the oldest of the three mail records that protect a domain from forgery, and the one most often published and then forgotten. A record can exist, look reasonable and still authorise the whole internet, break silently when a supplier adds a server, or pass without doing anything for DMARC. This guide explains how the record is read, so you can tell which of those applies to yours.
The examples use example.com. Replace it with your own domain.
What an SPF record is
Sender Policy Framework (RFC 7208) lets a domain list the servers allowed to send mail using that domain in the envelope sender, the address in the SMTP MAIL FROM command. Receivers see it later as Return-Path. It is a single TXT record at the domain name itself:
example.com. 3600 IN TXT "v=spf1 ip4:192.0.2.10 include:_spf.google.com ~all"
A receiving server takes the IP address the message came from and walks the record from left to right. The first term that matches decides the result. If nothing matches, the all at the end decides.
Two rules catch people out:
- One record per name. A domain with two TXT records that start with
v=spf1has an invalid SPF setup. RFC 7208 says receivers must returnpermerror, and most then ignore SPF for that domain. This usually happens when a new supplier's setup guide says “add this SPF record” and someone does, next to the existing one. Merge them into one. - No inheritance. SPF is looked up for the exact domain in the envelope sender.
news.example.comdoes not inherit the record onexample.com. Every name you send from, or bounce to, needs its own record.
The parts of the record
| Term | What it matches | Counts as a DNS lookup |
|---|---|---|
ip4:192.0.2.0/24 | The sending address is in this IPv4 range | No |
ip6:2001:db8::/32 | The sending address is in this IPv6 range | No |
a | The sending address is an A or AAAA record of the domain itself | Yes |
a:mail.example.com | The sending address is an A or AAAA record of the named host | Yes |
mx | The sending address belongs to one of the domain's MX hosts | Yes |
include:_spf.provider.example | The other domain's SPF record would pass this address | Yes, plus every lookup inside it |
exists:... | A constructed name resolves (used for advanced setups) | Yes |
ptr | Reverse DNS of the sender. RFC 7208 says not to use it | Yes |
redirect=_spf.example.com | Use another domain's record instead, if nothing else matched | Yes |
all | Everything. Always last | No |
Each mechanism can carry a qualifier in front of it. + means pass and is the default, so ip4:192.0.2.10 and +ip4:192.0.2.10 mean the same. - means fail, ~ means softfail and ? means neutral. In practice the qualifier that matters is the one on all.
How the record ends: ~all, -all, ?all and +all
The all mechanism answers the question “what about everyone else?”.
| Ending | Result for unlisted servers | What it means in practice |
|---|---|---|
-all | fail | Only the listed servers may send. Anything else is not authorised. |
~all | softfail | Unlisted servers are probably not authorised. Accept the message, but treat it with suspicion. |
?all | neutral | The domain makes no statement about unlisted servers. |
+all or a bare all | pass | Every server on the internet is authorised. |
No all and no redirect | neutral | The same as ?all (RFC 7208, section 4.7). |
+all is never right. It turns SPF into a pass for anyone, including a forger, while the record still looks configured. ?all and a missing all leave receivers with no instruction, which gives no protection against spoofing.
The choice between ~all and -all matters less than it used to, because DMARC now makes the delivery decision on most large receivers. Both are fine:
~allis the common choice for domains that send mail. Some receivers reject a message outright on an SPFfailbefore they evaluate DMARC or DKIM. RFC 7489 (section 10.1) warns about exactly this. With~all, a forwarded message that fails SPF still gets its chance to pass DMARC on an aligned DKIM signature.-allis the right choice for a domain that never sends mail, together with a DMARC record atp=reject. It is also reasonable for a sending domain whose every sender is known and signs with DKIM.
; a domain that sends mail through Microsoft 365 and one newsletter platform
example.com. 3600 IN TXT "v=spf1 include:spf.protection.outlook.com include:spf.sender.example ~all"
; a parked domain that never sends mail
example.org. 3600 IN TXT "v=spf1 -all"
The ten-lookup limit
Evaluating SPF can make a receiver perform DNS lookups, so RFC 7208 (section 4.6.4) caps them. The terms that cause lookups, include, a, mx, ptr, exists and redirect, may together cause at most ten DNS lookups during one evaluation. ip4, ip6 and all do not count. Go over the limit and the result is permerror, which receivers treat like a broken record.
The limit counts the whole tree, not the terms you can see. Every include adds one lookup for itself and then every lookup in the record it points to, and in the records that record includes. The RFC also says receivers should allow no more than two lookups that return nothing (void lookups), so an include pointing at a name that no longer exists costs more than it seems.
Count it yourself. Start from your record and resolve every include:
dig +short TXT example.com
dig +short TXT _spf.google.com
dig +short TXT spf.protection.outlook.com
Add one for each include, a, mx, exists or redirect you meet, at every level. The totals change when a provider restructures its own record, so a count that was eight last year can be eleven today without anyone on your side touching DNS.
SaaS senders and include chains
Most organisations reach the limit through suppliers. A mail platform, a CRM, a support desk, a newsletter tool, an invoicing system and a recruitment tool can each ask for an include, and some large providers' records nest three or four further lookups inside their own.
Before adding another include, ask two questions.
- Does this service actually send with my domain in the envelope sender? Many platforms send with their own bounce domain, for example
bounces.sender.example. Receivers then check SPF for that domain, not yours, and yourincludeis never consulted. It costs a lookup and does nothing. - Can the service sign with DKIM under my domain instead? An aligned DKIM signature satisfies DMARC on its own, survives forwarding, and costs no SPF lookups.
Other ways to stay under ten:
- Remove includes for services you no longer use. Old includes are the most common waste. Check the DMARC aggregate reports for which sources still send.
- Move bulk senders to a subdomain. Give the newsletter platform
news.example.comwith its own SPF record, DKIM key and bounce domain. The main domain's record stays short. - Replace
aandmxwith addresses where the hosts are yours and stable.mxis often included out of habit on domains whose MX hosts never send outbound mail.
Flattening, and why it breaks
Flattening means replacing include terms with the IP ranges they currently resolve to, so the record needs no lookups:
example.com. 3600 IN TXT "v=spf1 ip4:192.0.2.0/24 ip4:198.51.100.0/24 ip6:2001:db8::/32 ~all"
It solves the count and creates a maintenance problem. Providers change their sending ranges when they add capacity or move data centres, and they change them in their own include record, which you are no longer reading. When that happens, mail from new addresses fails SPF, often weeks after the flattening, with nothing to connect the failure to the change.
Flattened records also grow long. A TXT record is split into strings of at most 255 characters, and RFC 7208 advises keeping the whole SPF response small enough to fit a single DNS reply. A record that has grown past that can fail for some receivers.
If you flatten, do it with a tool or service that re-resolves the provider records on a schedule and republishes automatically, and keep the provider's own include for anything that tool does not cover. Hand-flattened records are a common cause of SPF failures that nobody can explain.
SPF and DMARC alignment
Passing SPF is not the same as passing DMARC. DMARC (RFC 7489) asks for SPF to pass and to be aligned: the envelope sender domain SPF checked must match the domain in the visible From header. By default the match is relaxed, so bounces.example.com aligns with example.com.
This is why a third-party platform can show “SPF: pass” in every report and still fail DMARC for your domain. It passed SPF for its own bounce domain, which is not yours. The fix is either a custom bounce (return-path) domain under your domain, if the platform offers one, or an aligned DKIM signature, which is usually easier.
A message passes DMARC if SPF or DKIM passes with alignment. Aim for DKIM on every sender and treat SPF as the second route, not the only one. The DMARC guide walks through the whole rollout.
How TrustSek scores SPF
TrustSek reads the SPF record your domain publishes in DNS, as part of the email security module. It is one reading at one point in time. What a scan reports:
| What the scan finds | Finding | Severity |
|---|---|---|
| No SPF record | SPF record missing | Medium |
| More than one SPF record on the domain | SPF record invalid | Medium |
A record ending in +all, or a bare all | SPF authorises all senders | High |
A record with no all and no redirect | SPF record has no all mechanism | Medium |
A record ending in ~all, -all or ?all | No SPF finding |
Three limits are worth knowing. The scan does not follow include chains or count DNS lookups, so a record over the ten-lookup limit is not flagged: count it yourself as described above. A record ending in ?all raises no finding, although it protects no better than a record with no all; prefer ~all or -all. And a record that passes all of this still does nothing for DMARC unless your senders are aligned. The SPF check page summarises the results, and the methodology explains how severity feeds the score.
A short checklist
One v=spf1 record per sending name. End it with ~all, or -all if the domain never sends. Count the lookups, includes and all, and stay under ten. Remove includes for services that no longer send, or that use their own bounce domain. Give bulk senders a subdomain. Get DKIM aligned for every sender, so DMARC does not depend on SPF alone.
Check your domain's SPF and the rest of its email security
See how your SPF record ends today, alongside DMARC, DKIM, MTA-STS and the rest of the outside-in score.