SPF Technical Reference (RFC 7208)
A section-by-section walkthrough of RFC 7208, the standard that defines SPF. Covers every mechanism, qualifier, the 10-lookup limit, void lookups, ptr deprecation, macros, and security considerations — with practical examples and tool links.
What RFC 7208 Defines
RFC 7208 is the authoritative specification for the Sender Policy Framework (SPF). Published in April 2014 by the IETF, it supersedes RFC 4408 and defines how domain owners declare which IP addresses are authorized to send email on their behalf, and how receiving mail servers evaluate those declarations.
Every SPF check your email goes through — at Gmail, Microsoft 365, Yahoo, or any other receiver — follows the rules in this document. When our SPF Checker reports a PermError, a lookup count, or a deprecated mechanism, the source is RFC 7208.
This reference walks through the sections that matter to email administrators, with the RFC's own language quoted where it clarifies the rule, followed by practical explanations and links to mxio tools and fix-it guides.
§3.1 — The v=spf1 Prefix and DNS Record Type
"An SPF record is a DNS Resource Record (RR) of type TXT [...] An SPF record begins with a version tag of 'v=spf1'."
Every SPF record is published as a TXT record and must begin with exactly v=spf1. The prefix is case-insensitive (V=spf1 and v=SPF1 are equivalent), but lowercase is conventional. Records that begin with any other version string are ignored by SPF evaluation.
The RFC originally defined a dedicated SPF DNS record type (type 99), but it was never widely adopted. §3.1 states that implementations "MUST NOT use type SPF" and must use TXT records exclusively. If you see an SPF-type record in your DNS, it has no effect.
Check it: The mxio SPF Checker validates the version prefix and warns if no valid v=spf1 record is found.
§3.2 — The One-Record Rule
"A domain name MUST NOT have multiple records that would cause an authorization check to select more than one record."
A domain may have exactly one SPF record. If two or more TXT records begin with v=spf1, the evaluation produces a PermError — a permanent failure applied to every message, regardless of whether the sending IP appears in either record.
This is the single most common SPF misconfiguration. It happens when an administrator adds a new SPF record (for a SaaS service, a marketing platform, or a migration) without merging it into the existing one.
Fix it: See Multiple SPF Records on One Domain for the step-by-step merge process.
Build it right: Use the mxio SPF Builder to generate a single, correct record from your selected providers.
§3.4 — Record Evaluation Order
SPF mechanisms are evaluated left to right. The first mechanism that matches the sending IP determines the result. Evaluation stops immediately — no further mechanisms are checked.
This has practical consequences for record optimization:
- Put high-volume senders first. If 90% of your email flows through Google Workspace,
include:_spf.google.comshould appear before less-used includes. The sooner a match is found, the fewer DNS lookups the evaluator performs. - Order does not affect the lookup count. All
include,a,mx,redirect, andexistsmechanisms count against the 10-lookup limit regardless of evaluation order. But placing frequent matches early reduces the actual DNS queries made per message.
§4.5 — Qualifiers: +, -, ~, ?
Every mechanism has a qualifier that determines the SPF result when that mechanism matches. If no qualifier is written, + (Pass) is implied.
| Qualifier | Result | Meaning |
|---|---|---|
+ |
Pass | The sender is authorized |
- |
Fail | The sender is not authorized — reject |
~ |
SoftFail | The sender is probably not authorized — accept but mark |
? |
Neutral | The domain makes no assertion about this sender |
The qualifier that matters most is the one on your all mechanism — the catch-all at the end of the record. -all tells receivers to reject unauthorized senders. ~all tells them to accept but treat with suspicion.
When to use which: See SPF ~all vs -all: Softfail vs Hardfail for the tradeoffs, including how each interacts with DMARC and forwarding.
§4.6.4 — The 10-Lookup Limit
"SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check."
This is the constraint that drives the entire SPF flattening industry. RFC 7208 caps the total number of DNS-querying mechanisms at 10. Mechanisms that count include:
| Mechanism | Lookup Cost |
|---|---|
include: |
1 (plus the lookups in the included record, recursively) |
a / a: |
1 |
mx / mx: |
1 (plus additional A lookups for each MX host) |
redirect= |
1 |
exists: |
1 |
ptr / ptr: |
1 |
Mechanisms that do not consume lookups:
| Mechanism | Lookup Cost |
|---|---|
ip4: |
0 — direct CIDR match |
ip6: |
0 — direct CIDR match |
all |
0 — always matches, no DNS query |
When the limit is exceeded, the evaluator returns PermError — a permanent failure. Every email from every IP is treated as failing SPF, regardless of whether the sender is listed in the record. This is not a warning. It is a hard failure.
Check it: Run the mxio SPF Checker to see your exact lookup count, broken down by mechanism.
Fix it: See Fix SPF PermError: Too Many DNS Lookups for reduction strategies, or learn about SPF flattening to resolve includes into IP addresses automatically.
The 2 Void-Lookup Limit
The same section imposes a lesser-known constraint:
"SPF implementations SHOULD limit the number of 'void lookups' to two."
A void lookup is a DNS query that returns either NXDOMAIN (the name does not exist) or an empty answer (the name exists but has no records of the queried type). If more than 2 void lookups occur during evaluation, the implementation "SHOULD" (strong recommendation, per RFC 2119) return a PermError.
This catches stale include mechanisms that point to domains that no longer publish SPF records. If you have removed a sending service but left its include: in your SPF record, and that domain's SPF TXT record has been deleted, every query against it produces a void lookup.
The mxio SPF Checker reports your void lookup count alongside the main lookup budget.
§5 — Mechanisms
§5.1 — all
The catch-all mechanism matches every sender. It must appear last in the record — any mechanisms after all are never evaluated. The qualifier on all sets the default policy:
-all— strict: reject anyone not explicitly authorized~all— permissive: accept but mark unauthorized senders+all— open: authorize everyone (defeats the purpose of SPF entirely)
A record without an all mechanism defaults to ?all (Neutral), which provides no protection.
§5.2 — include:
"If the 'include' target does not have a valid SPF record, this results in a 'PermError'."
The include mechanism delegates evaluation to another domain's SPF record. It consumes 1 lookup, plus all lookups within the included record (recursively). This is where lookup counts grow fast — a single include:_spf.google.com can consume 3-4 lookups by the time Google's nested includes are resolved.
If the included domain has no SPF record, or if its record is malformed, the entire evaluation returns PermError — not just the include, but the whole check.
§5.3 — a and a:
Matches the A and AAAA records of the specified domain (or the current domain if no argument is given). Consumes 1 lookup. Useful when your web server also sends email.
§5.4 — mx and mx:
Matches the IP addresses of the domain's MX hosts. Consumes 1 lookup for the MX query, plus additional A/AAAA lookups for each MX hostname. The RFC limits the total MX names to 10 (separate from the 10-mechanism lookup limit) to prevent abuse.
§5.5 — ptr (Deprecated)
"This mechanism SHOULD NOT be used."
The RFC explicitly deprecates ptr. The mechanism performs a reverse DNS lookup on the sending IP, then a forward lookup on each returned hostname to verify the IP matches. This is slow (multiple round-trips), unreliable (many IPs lack PTR records or have misconfigured reverse DNS), and adds load to DNS infrastructure.
The mxio SPF Checker flags ptr mechanisms with a deprecation warning. If you have ptr in your record, replace it with explicit ip4: or ip6: ranges, or use a: to match the hostname directly.
§5.6–5.7 — ip4: and ip6:
Direct CIDR matching against IPv4 and IPv6 addresses. These mechanisms consume zero DNS lookups — the match is performed locally against the sending IP. This is why SPF flattening works: by resolving include mechanisms into ip4 and ip6 ranges, the lookup count drops to zero for those entries.
Syntax examples:
ip4:192.0.2.1— single addressip4:192.0.2.0/24— CIDR rangeip6:2001:db8::/32— IPv6 prefix
§5.8 — exists:
A specialized mechanism that passes if a DNS A lookup for the given domain returns any result. Used primarily with macros (§8) for complex per-sender policies. Most organizations never need exists.
§6.1 — The redirect= Modifier
"If all mechanisms fail to match, and a 'redirect' modifier is present, [...] the check_host() function is evaluated with the domain from the redirect."
The redirect modifier replaces the current policy entirely with another domain's SPF record. Unlike include (which only delegates a portion of the check), redirect defers the entire evaluation. It is useful for organizations that maintain a single canonical SPF record and want all their domains to reference it.
redirect is only evaluated if no mechanisms match — so if an all mechanism is present, redirect is never reached. This is a common misconfiguration: having both ~all and redirect= in the same record. The ~all catches everything, making the redirect dead code.
§8 — Macros
RFC 7208 defines a macro language that allows SPF records to include dynamic values derived from the SMTP transaction: %{s} (sender), %{l} (local-part), %{d} (domain), %{i} (sending IP), and others.
Macros enable per-sender or per-IP policy lookups without maintaining a monolithic record. For example, exists:%{i}._spf.example.com checks whether a specific sending IP has a corresponding DNS entry — effectively creating a dynamic whitelist.
In practice, macros are rare outside enterprise deployments and anti-spam services. Most organizations use standard include, ip4, and ip6 mechanisms. If you encounter macros in an SPF record, the mxio SPF Checker parses and evaluates them correctly.
§10 — Security Considerations
The RFC's security section contains several important caveats that every email administrator should understand:
SPF Does Not Authenticate the From: Header
SPF authenticates the envelope sender (the MAIL FROM / Return-Path address), not the From: header that the recipient sees in their email client. An attacker can set a valid SPF Return-Path of attacker@evil.com while displaying ceo@yourcompany.com in the From: header.
This is exactly the gap that DMARC fills. DMARC requires that the domain authenticated by SPF (or DKIM) aligns with the From: header domain. Without DMARC, SPF alone does not prevent display-name spoofing.
For a complete explanation of how SPF, DKIM, and DMARC work together, see the Email Authentication Guide.
SPF Breaks on Forwarding
When an email is forwarded, the forwarding server's IP is not in the original sender's SPF record. SPF fails. This is inherent to the protocol's design — SPF checks the immediate connecting server's IP, not the original sender.
This is why DKIM and ARC (RFC 8617) are essential complements to SPF. DKIM signatures travel with the message and survive forwarding (if the body is not modified). ARC preserves the original authentication results across forwarding hops.
Quick Reference: Tool Checks and RFC Sections
| What the SPF Checker Reports | RFC 7208 Section |
|---|---|
Missing or invalid v=spf1 prefix |
§3.1 |
| Multiple SPF records (PermError) | §3.2 |
| Lookup count over 10 (PermError) | §4.6.4 |
| Void lookup count over 2 | §4.6.4 |
+all or no all policy |
§4.5, §5.1 |
ptr mechanism (deprecated) |
§5.5 |
| Include chain errors | §5.2 |
| Qualifier meanings (+, -, ~, ?) | §4.5 |
Full RFC Citation
Kitterman, S., "Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1", RFC 7208, DOI 10.17487/RFC7208, April 2014.
Excerpts from RFC 7208 are Copyright © 2014 IETF Trust and the persons identified as the document authors. All rights reserved. The full text of the RFC is available at rfc-editor.org.
Related Articles
Your SPF record exceeds the 10-lookup limit, causing email authentication failures. Learn why this happens and how to fix it with step-by-step instructions.
Having more than one SPF TXT record on a domain causes both to fail. Learn how to detect duplicate SPF records and merge them correctly.
Should your SPF record end with ~all (softfail) or -all (hardfail)? Understand the difference, when to use each, and the impact on email delivery.
SPF flattening resolves include mechanisms to IP addresses, reducing DNS lookups. Learn how it works, the risks of manual flattening, and when you need automated flattening.
Build a correct SPF record for your domain using the mxio SPF Builder. Select your email providers, set your policy, and publish with confidence.
Understand how SPF, DKIM, and DMARC work together to protect your domain from spoofing and improve email deliverability. A practical guide for email administrators.