SPF Record Syntax: Complete Guide to Mechanisms, Modifiers & Qualifiers
Everything you need to know about SPF syntax: v=spf1, include, ip4, ip6, a, mx, all, redirect, and exp. With examples and common mistakes to avoid.
SPF record syntax basics
An SPF record is a DNS TXT record published at your domain root. It always starts with v=spf1 followed by one or more mechanisms, and ends with an 'all' mechanism or 'redirect' modifier.
Example: v=spf1 include:_spf.google.com ip4:203.0.113.5 -all
This says: Google's servers and the IP 203.0.113.5 are authorized. Reject everything else.
SPF mechanisms explained
Each mechanism in an SPF record specifies a class of authorized senders. Mechanisms that require DNS resolution count toward the 10-lookup limit — mechanisms using IP addresses do not.
SPF mechanism reference
| Mechanism ↕ | Example ↕ | What It Authorizes ↕ | Counts as Lookup? ↕ |
|---|---|---|---|
| include: | include:_spf.google.com | All servers authorized by another domain's SPF record | Yes (+ sub-lookups) |
| ip4: | ip4:203.0.113.0/24 | A specific IPv4 address or CIDR range | No |
| ip6: | ip6:2001:db8::/32 | A specific IPv6 address or CIDR range | No |
| a | a:mail.example.com | IPs from the domain's A/AAAA record | Yes |
| mx | mx:example.com | IPs from the domain's MX records | Yes |
| exists: | exists:%{i}.check.example.com | Any IP where the DNS query returns a result (macro-based) | Yes |
| ptr | ptr:example.com | IPs with a PTR record matching the domain (deprecated) | Yes |
| all | -all or ~all | Every sender not matched by prior mechanisms (catch-all) | No |
SPF qualifiers
A qualifier prefix on any mechanism changes the result when that mechanism matches. The most important is the qualifier on `all` — the catch-all at the end of your record.
SPF qualifier reference
| Qualifier ↕ | Symbol ↕ | SMTP Result ↕ | Recommended Use ↕ |
|---|---|---|---|
| Pass | + (default) | PASS — sender is authorized | Omit prefix; it's the default when no qualifier is present |
| Fail | - | FAIL — hard reject unauthorized senders | Use as -all at the end (recommended for enforced SPF) |
| SoftFail | ~ | SOFTFAIL — accept but mark as suspicious | Use as ~all during initial rollout before -all |
| Neutral | ? | NEUTRAL — no assertion made | Avoid — provides zero spam protection |
# Minimal SPF (Google Workspace only)
v=spf1 include:_spf.google.com -all
# Multi-service SPF (Google + SendGrid + dedicated IP)
v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.5 -all
# Using ip4/ip6 instead of include: (saves lookup budget)
v=spf1 ip4:198.51.100.0/24 ip6:2001:db8::/32 -all10 DNS lookup limit
Each include:, a, mx, ptr, and exists counts toward the 10-lookup limit. Each include: also pulls in the sub-lookups from that domain's SPF record. Use ip4:/ip6: wherever you know the specific IPs.
SPF modifiers: redirect and exp
redirect=domain — Replaces the entire SPF evaluation with the target domain's SPF record. Use this when you want to delegate your SPF to another domain entirely.
exp=domain — Points to a TXT record containing an explanation string included in bounce messages. Rarely needed.
Important: redirect cannot be used alongside 'all' — they're mutually exclusive.
Common SPF mistakes
1. Exceeding 10 DNS lookups — each include, a, mx, exists, and redirect counts. Use ip4/ip6 where possible. 2. Multiple SPF records — only one TXT record starting with 'v=spf1' is allowed per domain. 3. Including sending services you don't use — creates confusion and wastes lookup budget. 4. Using ?all — provides no protection whatsoever. 5. Forgetting third-party senders like Mailchimp, HubSpot, or SendGrid. 6. Very long records — single strings over 255 characters need to be split (but most DNS providers handle this automatically).
Check your domain's email health
Run a free scan against 60 blacklists. Validate SPF, DKIM, DMARC, and MX records in seconds.
Related free tools