SPF Explained: Sender Policy Framework, RFC 7208, Mechanisms, Qualifiers, and the 10-Lookup Limit

Everything a domain owner needs to publish, validate, and maintain a Sender Policy Framework record — from minimal one-line records to multi-sender flattened deployments — with full RFC 7208 syntax, the 10-lookup limit explained, and worked examples for Google Workspace, Microsoft 365, and transactional senders.

This reference is provided in English. SPF is specified in English-language RFCs and the canonical syntax (v=spf1, include:, -all) does not translate; we keep the body in the source language so technical terms are consistent with the specifications.

TL;DR

  • SPF (Sender Policy Framework, RFC 7208) is a DNS TXT record that lists the IP addresses authorised to send mail for a domain.
  • Receivers query the SPF record at the envelope-sender domain (MAIL FROM / Return-Path) and check the connecting IP against the published list.
  • Outcomes are pass, fail, softfail, neutral, none, temperror, or permerror.
  • SPF has a hard 10-DNS-lookup limit (RFC 7208 §4.6.4). Exceeding it returns permerror and fails authentication.
  • SPF authenticates the envelope sender, not the visible From: header — an attacker can pass SPF on their own domain while spoofing you in From:. SPF must be combined with DMARC to actually stop spoofing.
  • Forwarding breaks SPF: the forwarder rewrites the envelope, so the receiver sees an unauthorised IP. DKIM survives forwarding; that is why DMARC alignment typically depends on DKIM, not SPF.

1. What is SPF?

SPF (Sender Policy Framework) is an email authentication standard defined in RFC 7208 that lets a domain owner publish a DNS TXT record listing the IP addresses (or hostnames, or other SPF records) authorised to originate mail on the domain's behalf. When a receiving mail server accepts an SMTP connection, it extracts the envelope sender's domain (MAIL FROM), looks up that domain's SPF record, and checks whether the connecting IP is on the authorised list.

SPF was originally specified in RFC 4408 (2006) and obsoleted by RFC 7208 (April 2014, the current standard). It is one of three complementary email-authentication primitives — alongside DKIM (cryptographic signing) and DMARC (policy + reporting) — that together harden SMTP against spoofing, phishing, and brand impersonation.

Crucially, SPF authenticates only the envelope sender (the MAIL FROM address used during SMTP negotiation), not the header From: address users actually see in their inbox. An attacker can publish a permissive SPF record on a domain they control, pass SPF against that domain, and still write any value they like in the From: header. SPF alone does not stop spoofing — that gap is exactly what DMARC was invented to close.

2. How SPF works, step by step

  1. A sender connects to a receiving mail server and issues MAIL FROM:<billing@example.com> during SMTP negotiation.
  2. The receiver extracts the envelope-sender domain (example.com) and queries DNS for the TXT record at that name. SPF records start with v=spf1 and end with an all mechanism.
  3. The receiver evaluates each mechanism left-to-right against the connecting IP. The first matching mechanism produces a result — pass, fail, softfail, or neutral — and evaluation stops.
  4. If no mechanism matches before the terminating all, the all mechanism's qualifier (+/-/~/?) produces the final result.
  5. The result is recorded in the message's Authentication-Results: header and is consumed downstream by the DMARC evaluator (for alignment with the From: domain) and by anti-spam scoring engines.

Two extra SPF-result conditions exist outside the mechanism-matching loop:

  • none — the domain published no SPF record at all.
  • temperror — a transient DNS failure (e.g. timeout). Receivers SHOULD defer (4xx) and retry.
  • permerror — the SPF record is malformed, recursive, or exceeds the 10-lookup limit. Permanent failure; SPF cannot authenticate the message.

3. SPF DNS syntax

An SPF record is a single TXT record at the domain apex:

example.com.   IN   TXT   "v=spf1 ip4:198.51.100.0/24 include:_spf.google.com ~all"

Anatomy:

v=spf1
Version tag. Must appear first; without it the record is not an SPF record. RFC 7208 §4.5 requires exactly one v=spf1 TXT record per domain — two records returns permerror.
Mechanisms (ip4, ip6, a, mx, include, exists, ptr, all)
Each mechanism defines a set of IPs to match against the connecting IP. Evaluated left-to-right; first match wins. See §4 below for each one.
Qualifiers (+, -, ~, ?)
Prefix each mechanism. Define the result on match: + pass (default), - fail, ~ softfail, ? neutral. See §5 below.
Modifiers (redirect=, exp=)
Optional. redirect= outsources evaluation to another domain's SPF record; exp= publishes an explanation string for SPF failures (rarely used).

The record must be ASCII-safe and ≤ 255 characters per TXT string (DNS limit). Longer records are split into multiple double-quoted strings within the same TXT record — DNS resolvers concatenate them on receipt.

4. SPF mechanisms explained

ip4:<cidr> / ip6:<cidr>
Direct IP-range authorisation. Costs zero DNS lookups — preferred for performance and for staying inside the 10-lookup limit. Example: ip4:198.51.100.0/24.
include:<domain>
Outsources the IP list to another domain's SPF record. The most common mechanism — used to delegate to SaaS senders (e.g. include:_spf.google.com for Google Workspace, include:spf.mandrillapp.com for Mandrill). Costs one DNS lookup per include, plus any lookups the included record itself triggers — the total counts toward the 10-lookup limit.
a / a:<domain>
Authorises every IP returned by the domain's A/AAAA record. With no argument it uses the SPF record's own domain. Costs one DNS lookup.
mx / mx:<domain>
Authorises every IP of the domain's MX hosts. Tempting (it tracks your inbound mail servers) but often wrong — the inbound MX servers are usually NOT the outbound sending servers. Costs one DNS lookup against the limit of 10; the address lookups for the MX hosts are capped separately, at 10.
ptr
Deprecated. RFC 7208 §5.5 explicitly SHOULD NOT be used. Performs a reverse DNS lookup on the connecting IP and matches against the PTR record. Slow, fragile, and easily spoofed. Never use in new SPF records.
exists:<domain>
Passes if the named domain has any A record. Used for macro-driven per-IP whitelisting (e.g. exists:%{ir}.spf.example.com creates a per-IP DNS-based whitelist). Costs one DNS lookup. Rare; mostly used by large senders.
all
The catch-all mechanism, MUST appear last. Matches every IP. The qualifier on all (-all, ~all, ?all, +all) determines the result for any IP not matched by earlier mechanisms. Costs zero DNS lookups.

5. SPF qualifiers explained

Each mechanism may be prefixed by a qualifier that determines the SPF result on a match. The qualifier only matters on the matching mechanism — others are silently skipped.

Qualifier Result on match Receiver action When to use
+ (implicit default) pass Deliver normally All legitimate sender mechanisms
- fail (hardfail) Reject (5xx SMTP) Terminating -all in production
~ softfail Accept but mark suspicious (often → spam) Terminating ~all during rollout
? neutral No policy guidance, treat as none Rare; effectively disables SPF for that match

Production guidance: end every SPF record with -all (hardfail) once you have confirmed all legitimate senders are listed. Use ~all only during the initial rollout window when you are still discovering shadow senders.

6. The SPF 10-lookup limit

RFC 7208 §4.6.4 caps the number of DNS queries an SPF evaluation may perform at 10. The cap exists to prevent SPF from being weaponised into a DNS-amplification DoS vector. Each of these mechanisms counts as 1 lookup toward the cap:

  • include (plus all lookups inside the included record)
  • a
  • mx (the address lookups for its MX hosts have their own cap of 10)
  • ptr (deprecated; do not use)
  • exists
  • redirect= modifier

ip4, ip6, and all cost zero lookups — they are evaluated against the connecting IP directly without DNS.

Exceeding the cap returns permerror, which fails authentication for every recipient — not just the ones causing the overflow. A permerror result is also a DMARC fail, so an over-budget SPF record can take down legitimate mail flow on every receiver that honours DMARC.

Domains with many third-party senders typically use SPF flattening — periodically resolving include chains down to their underlying ip4/ip6 ranges and republishing the flattened record. Flattening trades one operational cost (a daily/weekly cron to re-resolve includes) for one architectural risk (your record diverges from the upstream sender's truth until the next refresh). Use the DNS Generator tool to model a flat record before publishing it.

7. SPF examples

7.1 Google Workspace only

example.com.   IN   TXT   "v=spf1 include:_spf.google.com -all"

Authorises every Google Workspace sending IP and rejects every other source. Suitable for a single- tenant Google Workspace deployment with no transactional senders.

7.2 Google Workspace + Microsoft 365 (hybrid)

example.com.   IN   TXT   "v=spf1 include:_spf.google.com include:spf.protection.outlook.com -all"

Two SaaS senders combined into one record. Two include lookups consumed (~5-7 internal lookups total inside the includes); plenty of headroom inside the 10-lookup limit.

7.3 Google Workspace + Mailgun + on-prem relay

example.com.   IN   TXT   "v=spf1 ip4:198.51.100.10 include:_spf.google.com include:mailgun.org -all"

Direct IP authorisation (ip4:, costs 0 lookups) for an on-prem MTA, plus two SaaS includes. Total lookup cost is dominated by the includes, not the ip4:.

7.4 Non-sending domain — block everything

example.com.   IN   TXT   "v=spf1 -all"

A "null SPF" record. Use on every domain that does NOT send legitimate mail — parked domains, brand look-alikes, internal-only domains. Publishing v=spf1 -all on a non-sending domain is the single most effective anti-spoofing measure available for that domain.

7.5 Subdomain delegation

news.example.com.   IN   TXT   "v=spf1 include:spf.sendgrid.net -all"

Each subdomain has its own SPF record. Lets you scope different senders to different subdomains — e.g. SendGrid for marketing on news.example.com, Google Workspace for staff on example.com. A subdomain inherits NO SPF settings from the parent domain.

8. SPF best practices

  • Always terminate with -all in production. ~all is only acceptable during the first 2-4 weeks of rollout while you discover shadow senders.
  • Publish v=spf1 -all on every non-sending domain. Parked domains, brand look-alikes, and internal-only domains should explicitly refuse to authorise any sender.
  • Use ip4/ip6 over a/mx where the ranges are stable. Zero DNS lookups, faster evaluation, lookup-limit headroom.
  • Stay well inside the 10-lookup limit. Target ≤ 7 lookups so future SaaS additions do not push you over the cap. Flatten or consolidate if you approach 8.
  • Never use ptr. Deprecated, slow, and a security liability.
  • Combine with DKIM and DMARC. SPF alone is insufficient — see §10. Deploy all three in parallel; DMARC ties SPF and DKIM to the visible From: header.
  • Audit SPF records quarterly. Third- party senders change IPs; include chains grow; the 10-lookup margin erodes. Re-verify using a DNS validation tool.
  • Subdomain SPF is separate. Subdomains do NOT inherit the parent's SPF record. Publish an explicit SPF record (or a v=spf1 -all null record) on every subdomain that sends mail OR is at risk of being spoofed.

9. Common SPF mistakes

  • Publishing two v=spf1 TXT records. RFC 7208 §4.5 requires exactly one. Two records returns permerror and breaks authentication. Merge mechanisms into a single record instead.
  • Exceeding the 10-lookup limit. Especially common after adding a third or fourth SaaS sender. Use a validator that resolves the full include graph before publishing.
  • Ending with +all. Means "everyone passes" — equivalent to no SPF at all and defeats the entire point. Almost certainly a typo.
  • Forgetting to add a SaaS sender. Marketing tools, helpdesk platforms, e-signature services, and CI/CD systems all send mail on your behalf. Discover them via DMARC aggregate reports in this dashboard, then add the corresponding include: mechanism.
  • Trusting mx for outbound senders. Inbound MX servers are usually NOT outbound sending servers. Most cloud mail platforms (Google, Microsoft) separate them. Audit before adding mx.
  • Using ptr. Deprecated by RFC 7208. Mail forwarders rewriting HELO / EHLO hostnames cause it to fail unpredictably.
  • Treating SPF as a spoofing defence. SPF authenticates the envelope sender, not the visible From: header. Without DMARC, SPF cannot stop spoofing.

10. SPF troubleshooting

permerror — "Too many DNS lookups"
The include graph exceeds 10 lookups. Audit the chain (some SaaS providers' SPF records contain their own nested includes), then flatten or replace high-cost includes with direct ip4 ranges.
permerror — "Two SPF records"
Two TXT records starting with v=spf1 on the same domain. Merge their mechanisms into a single record and delete the duplicate.
fail from a legitimate sender
The sender's IP is not on your SPF list. Either (a) add the sender's include: mechanism, (b) authorise their direct ip4 range, or (c) confirm the sender is supposed to be sending on your behalf — many "missing" senders are actually unauthorised SaaS sign-ups or shadow IT.
fail when forwarded
Expected. Forwarders rewrite the envelope sender, so the receiver checks SPF against the forwarder's IP — which isn't on your list. DKIM survives forwarding and is what DMARC alignment depends on for forwarded traffic.
softfail on production traffic
Your record terminates with ~all instead of -all. Migrate to -all once you have confirmed every legitimate sender is listed.
temperror — intermittent failures
DNS resolver timeouts. Usually transient; if it persists, check authoritative-DNS reachability for every domain in the include chain.
none result
No SPF record found at the envelope-sender domain. Publish one — even v=spf1 -all on a non-sending domain prevents spoofing of that domain.

11. Frequently Asked Questions

What is SPF?
SPF (Sender Policy Framework, RFC 7208) is a DNS-based email authentication mechanism that lets a domain owner publish, as a DNS TXT record, the list of IP addresses authorised to send mail on the domain's behalf. Receiving mail servers query the SPF record to verify whether the connecting SMTP server is on the published list.
What does an SPF record look like?
An SPF record is a single DNS TXT record at the domain apex, starting with v=spf1 and ending with an all mechanism. A typical minimal record is: example.com. IN TXT "v=spf1 include:_spf.google.com -all" — authorising Google Workspace as the only sender and rejecting all other sources.
What is the SPF 10-lookup limit?
RFC 7208 §4.6.4 caps the number of DNS lookups an SPF evaluation may perform at 10 (include, a, mx, ptr, exists, and redirect each count). Exceeding the cap returns permerror and the SPF check fails for every recipient. Domains with many third-party senders must "flatten" their record (resolve include chains to ip4/ ip6 mechanisms) to stay inside the limit.
What is the difference between -all, ~all and ?all?
-all (hard fail) tells receivers to reject mail from unauthorised IPs. ~all (soft fail) marks unauthorised mail as suspicious but still delivers it. ?all (neutral) provides no policy guidance. Production SPF records should use -all once aligned senders are confirmed; ~all is the migration default during initial rollout.
Why does SPF break when mail is forwarded?
SPF authenticates the SMTP envelope sender (MAIL FROM / Return-Path), which is rewritten by most forwarders to their own bounce address. The receiver then sees a forwarder IP not on the original domain's SPF list, producing a fail. This is why DKIM — which signs the message content and survives forwarding — is the alignment mechanism DMARC relies on for forwarded traffic.
Is SPF alone enough to stop spoofing?
No. SPF authenticates the envelope sender, not the visible From: header users see. An attacker can publish a permissive SPF record on their own domain and pass SPF while still showing your domain in From:. DMARC closes this gap by requiring SPF or DKIM authentication AND identifier alignment with the From: header.
Can I publish multiple SPF records for one domain?
No. RFC 7208 §4.5 requires exactly one v=spf1 TXT record per domain. Two SPF records returns permerror and breaks authentication. To combine senders, merge their mechanisms into a single record (e.g. v=spf1 include:_spf.google.com include:spf.mandrillapp.com -all).

13. Audit your SPF record now

DMARC Analyzer's free Domain Security Checker performs live SPF lookups, validates the syntax against RFC 7208, counts DNS lookups against the 10-lookup limit, and flags every common misconfiguration covered above. Imported aggregate reports also show every IP that actually attempted to send mail for your domain — the surest way to find shadow senders missing from your SPF record.

Check my SPF record Sign up — Free plan