SPF records can look cryptic at first glance. A string like v=spf1 include:_spf.google.com ip4:192.168.1.1 ~all contains a lot of meaning packed into a short format. Understanding this syntax is essential for building effective SPF records and troubleshooting authentication issues.
This reference guide breaks down every component of SPF record syntax with practical examples you can apply to your own domain.
SPF Record Structure
Every SPF record follows this basic structure:
v=spf1 [mechanisms] [modifiers]
Let's examine each component.
The Version Tag
v=spf1
Every SPF record must start with this version identifier. It tells email receivers this is an SPF version 1 record. There is no SPF version 2—despite the name, the "Sender ID" proposal (sometimes called SPFv2) never became widely adopted.
Important: This must be the very first thing in the record. No spaces before it.
Qualifiers
Qualifiers appear before mechanisms and determine what happens when a mechanism matches. There are four qualifiers:
| Qualifier | Symbol | Result | Meaning |
|---|---|---|---|
| Pass | + |
Pass | This source is authorized (default if no qualifier) |
| Fail | - |
Fail | This source is NOT authorized—reject |
| SoftFail | ~ |
SoftFail | This source is probably not authorized—accept but mark |
| Neutral | ? |
Neutral | No assertion—treat as if no SPF exists |
If no qualifier is specified, + (Pass) is assumed. So ip4:192.168.1.1 is the same as +ip4:192.168.1.1.
Mechanisms
Mechanisms are the core of SPF—they define which servers are authorized to send email for your domain.
all
Matches everything. Used at the end of a record to define the default action.
v=spf1 include:_spf.google.com -all
Common usage patterns:
-
-all— Reject anything not explicitly authorized (hardfail) -
~all— Accept but mark as suspicious (softfail) -
?all— Neutral, no default policy -
+all— Allow anyone (never use this—it defeats the purpose of SPF)
ip4
Matches a specific IPv4 address or range.
ip4:192.168.1.1 (single IP)
ip4:192.168.1.0/24 (CIDR range - 256 IPs)
Use this when you know the exact IP addresses of your mail servers.
ip6
Matches a specific IPv6 address or range.
ip6:2001:db8::1 (single IP)
ip6:2001:db8::/32 (CIDR range)
a
Matches the A record (IPv4) or AAAA record (IPv6) of a domain.
a (matches your domain's A record)
a:mail.example.com (matches that domain's A record)
a/24 (matches your domain's A record with /24 CIDR)
Useful when your web server and mail server share an IP, or when a server's IP might change but its hostname won't.
mx
Matches the IP addresses of your domain's MX (mail exchange) records.
mx (your domain's MX servers)
mx:example.com (that domain's MX servers)
mx/24 (your MX servers with /24 CIDR)
Common for domains where inbound and outbound mail use the same servers.
include
Includes another domain's SPF record. This is how you authorize third-party email services.
include:_spf.google.com (Google Workspace)
include:servers.mcsv.net (Mailchimp)
include:sendgrid.net (SendGrid)
include:spf.protection.outlook.com (Microsoft 365)
Important: Each include counts toward your 10 DNS lookup limit. The included domain's SPF may also contain more includes, which also count.
exists
Matches if a specific domain exists in DNS (regardless of what it resolves to).
exists:%{i}._spf.example.com
Advanced mechanism used for per-IP authorization or macro-based lookups. Rarely needed for typical configurations.
ptr (Deprecated)
Matches based on reverse DNS lookup. Do not use.
ptr (deprecated)
ptr:example.com (deprecated)
This mechanism is deprecated in RFC 7208 because it's slow, unreliable, and causes excessive DNS queries. Modern SPF validators may ignore it.
Modifiers
Modifiers provide additional information but don't directly authorize senders.
redirect
Replaces the current SPF evaluation with another domain's SPF record.
v=spf1 redirect=_spf.example.com
Key difference from include:
-
include— If the included record doesn't match, continue evaluating -
redirect— Completely replace this record with the target's SPF
Use redirect when a domain's entire SPF policy should be defined elsewhere (like for subdomains or aliased domains).
exp
Specifies a domain containing an explanation message for failures.
v=spf1 include:_spf.google.com -all exp=explain._spf.example.com
The TXT record at the explanation domain contains a human-readable message about why the email failed. Rarely used in practice.
Practical Examples
Google Workspace Only
v=spf1 include:_spf.google.com -all
Microsoft 365 Only
v=spf1 include:spf.protection.outlook.com -all
Multiple Services
v=spf1 include:_spf.google.com include:servers.mcsv.net include:sendgrid.net -all
Own Mail Server Plus Services
v=spf1 ip4:203.0.113.10 include:_spf.google.com include:amazonses.com -all
Subdomain with Redirect
For a subdomain that should use the parent domain's SPF:
v=spf1 redirect=example.com
No Email from This Domain
For domains that should never send email:
v=spf1 -all
Macros (Advanced)
SPF supports macros for dynamic lookups. These are rarely needed but powerful for complex configurations.
| Macro | Meaning |
|---|---|
%{s} |
Sender (the MAIL FROM address) |
%{l} |
Local part of sender (before the @) |
%{o} |
Domain of sender |
%{d} |
Domain being checked |
%{i} |
IP address of connecting server |
%{h} |
HELO/EHLO domain |
%{v} |
IP version (in4 or in6) |
Example using macro for per-IP lookup:
v=spf1 exists:%{i}._spf.example.com -all
This checks if a DNS record exists for each connecting IP, allowing granular per-IP authorization.
Common Syntax Errors
Missing Version Tag
❌ include:_spf.google.com -all
✅ v=spf1 include:_spf.google.com -all
Multiple SPF Records
You can only have one SPF record per domain. Multiple records cause failures.
❌ Two separate TXT records
✅ One record with all mechanisms combined
Missing all Mechanism
Without an all at the end, there's no default policy.
❌ v=spf1 include:_spf.google.com
✅ v=spf1 include:_spf.google.com -all
Using +all
Never use +all—it allows anyone to send as your domain.
❌ v=spf1 include:_spf.google.com +all
✅ v=spf1 include:_spf.google.com -all
Exceeding 10 DNS Lookups
The 10 DNS lookup limit includes all include, a, mx, ptr, and redirect mechanisms (including nested lookups).
Testing Your SPF Record
Before publishing, validate your SPF syntax with these tools:
- MxToolbox SPF Checker — Validates syntax and counts lookups
- Google Admin Toolbox — Check MX and SPF records
- SPF Record Testing Tools — Many free options available online
0 comments