SPF Record Syntax Explained (with Examples)
SPF (Sender Policy Framework) records are just DNS TXT records, but the syntax inside them has specific rules that are easy to get wrong. This is a reference for the mechanisms, qualifiers, and limits you’ll actually run into.
Basic structure
Every SPF record starts with a version tag and ends with an “all” mechanism:
v=spf1 [mechanisms] [qualifier]all
Example:
v=spf1 include:_spf.google.com -all
The version tag
v=spf1 must be the first term in the record, exactly as written. This isn’t a mechanism — it’s what identifies the TXT record as an SPF record at all. Without it, the record is ignored during SPF evaluation.
Mechanisms
Mechanisms define which sources are authorized to send mail for the domain.
| Mechanism | Meaning |
|---|---|
a | Authorizes the domain’s own A/AAAA record IP(s) |
mx | Authorizes the domain’s MX record IP(s) |
ip4:1.2.3.4 | Authorizes a specific IPv4 address or range |
ip6:2001:db8::1 | Authorizes a specific IPv6 address or range |
include:domain.com | Authorizes whatever the included domain’s SPF record authorizes |
all | Matches everything — always placed last |
Example combining several:
v=spf1 a mx ip4:203.0.113.10 include:_spf.google.com -all
Qualifiers
Each mechanism can be prefixed with a qualifier that determines what happens on a match:
| Qualifier | Symbol | Result |
|---|---|---|
| Pass | + (default, usually omitted) | Authorized |
| SoftFail | ~ | Probably not authorized, don’t reject outright |
| Fail | - | Not authorized, reject |
| Neutral | ? | No policy statement either way |
Qualifiers matter most on the final all mechanism:
v=spf1 include:_spf.google.com ~all
v=spf1 include:_spf.google.com -all
The first soft-fails anything not explicitly listed; the second hard-fails it.
The 10-lookup limit
This is the single most common cause of SPF breaking in production. SPF evaluation is capped at 10 DNS lookups total. Mechanisms that count toward this limit: include, a, mx, ptr, and exists. ip4 and ip6 do not count, since they don’t require a lookup.
Each include: can itself contain more include: statements, and all of them count. A record that looks short can still blow the limit if it includes a provider whose own SPF record has several nested includes. When the limit is exceeded, SPF returns a PermError, and receivers typically treat that as a fail — regardless of whether the actual sending server was legitimate.
Real-world examples
Google Workspace only:
v=spf1 include:_spf.google.com -all
Microsoft 365 only:
v=spf1 include:spf.protection.outlook.com -all
Google Workspace plus a third-party sending tool:
v=spf1 include:_spf.google.com include:sendgrid.net -all
Self-hosted mail server by IP:
v=spf1 ip4:203.0.113.10 -all
Only one SPF record per domain
A domain must have exactly one v=spf1 TXT record. If you need to authorize multiple providers, combine them into a single record with multiple include: mechanisms — don’t create separate TXT records for each provider. Two SPF records on the same domain causes SPF to fail entirely.
Checking your SPF record
Use the free SPF/DKIM/DMARC checker to validate your SPF syntax, or run a raw TXT record lookup to see the exact record as published.
Once SPF, DKIM, and DMARC are all correctly configured, the next variable in deliverability is sending reputation and volume ramp-up. MailPilot warms up new mailboxes gradually and monitors deliverability if you’re preparing a domain for cold email or sales outreach.