SPF Record Syntax: A Complete Reference Guide
Learn every SPF record syntax element including mechanisms, qualifiers, and modifiers. A plain-English guide with examples.
Last updated: 2026-04-11
SPF records look intimidating at first glance, but they follow a straightforward pattern. Once you understand the pieces, you can read, write, and troubleshoot any SPF record with confidence. This guide breaks down every part of the SPF record syntax in plain English. For a broader overview that covers syntax alongside setup and troubleshooting, see our complete SPF guide.
The Basic Structure
Every SPF record follows the same format:
v=spf1 [mechanisms] [qualifier]all
It always starts with v=spf1 (the version tag) and ends with an all mechanism. In between, you list the servers and services authorized to send email for your domain.
SPF records are TXT records
An SPF record is published as a DNS TXT record on your domain. There should only be one SPF record per domain. Having two causes errors.
The Version Tag: v=spf1
Every SPF record must begin with exactly v=spf1, as required by RFC 7208. This tells receiving mail servers that the TXT record is an SPF record. There are no other versions in use, so you will always use v=spf1.
Correct: v=spf1 include:_spf.google.com ~all
Wrong: spf1 include:_spf.google.com ~all (missing v=)
Wrong: v=spf2 include:_spf.google.com ~all (no such version)
SPF Mechanisms Explained
Mechanisms are the building blocks of an SPF record. Each one describes a way to check whether a sending server is authorized. Here is every mechanism you can use.
include
The include mechanism references another domain's SPF record. This is how you authorize third-party email services.
include:_spf.google.com
include:sendgrid.net
include:spf.protection.outlook.com
When a mail server evaluates your SPF record and hits an include, it looks up the SPF record for that domain and checks it too. Each include counts toward the 10 DNS lookup limit.
ip4
The ip4 mechanism authorizes a specific IPv4 address or range. Use this when you know the exact IP addresses of your mail servers.
ip4:203.0.113.5
ip4:198.51.100.0/24
The /24 notation (called CIDR) authorizes an entire range of 256 addresses. If you just list a single IP, no slash is needed.
ip6
Same as ip4, but for IPv6 addresses.
ip6:2001:db8::1
ip6:2001:db8::/32
a
The a mechanism checks if the sending server's IP matches the A record (or AAAA record) of your domain. If you host your own mail server on the same IP as your website, this can be useful.
v=spf1 a ~all
You can also reference another domain's A record:
a:mail.example.com
mx
The mx mechanism authorizes whatever servers are listed in your domain's MX records. Since MX records point to your mail servers, this is a logical shortcut.
v=spf1 mx ~all
Like a, you can reference another domain:
mx:example.com
ptr (not recommended)
The ptr mechanism does a reverse DNS lookup to check if the sending IP resolves back to your domain. It is slow, unreliable, and officially discouraged by the SPF specification (RFC 7208). Avoid using it.
exists
The exists mechanism checks whether a specific domain has an A record. It is used for advanced configurations and macro-based setups. Most small businesses will never need this.
exists:%{i}._spf.example.com
all
The all mechanism is a catch-all that matches everything. It always goes at the end of the record. Its behavior depends on the qualifier in front of it (see the next section).
Qualifiers: Pass, Fail, Soft Fail, Neutral
Every mechanism can have a qualifier prefix that determines the result when it matches. There are four qualifiers:
| Qualifier | Symbol | Meaning |
|-----------|--------|---------|
| Pass | + (or no symbol) | The server is authorized. This is the default. |
| Fail | - | The server is NOT authorized. Reject the email. |
| Soft Fail | ~ | The server is probably not authorized. Accept but mark it. |
| Neutral | ? | No opinion. Treat as if no SPF record exists. |
The qualifier goes directly before the mechanism. For example:
~all— Soft fail everything not already matched (most common)-all— Hard fail everything not already matched (strictest)+include:_spf.google.com— Same asinclude:_spf.google.com(pass is the default)
Start with ~all, upgrade to -all
Most administrators start with ~all (soft fail) while setting up. Once you have confirmed that all your legitimate sending services are listed, switch to -all (hard fail) for stronger protection against spoofing.
Modifiers: redirect and exp
SPF also has two modifiers. The redirect modifier replaces your entire SPF evaluation with another domain's SPF record, useful when multiple domains share the same policy. The exp modifier specifies a custom error message domain, but it is rarely used in practice.
v=spf1 redirect=_spf.example.com
Do not use redirect and all in the same record since redirect replaces the policy entirely.
Mechanism Comparison Table
| Mechanism | What It Does | Example | DNS Lookups |
|---|---|---|---|
| include | References another domain's SPF record | include:_spf.google.com | 1+ |
| ip4 | Authorizes an IPv4 address or range | ip4:203.0.113.0/24 | 0 |
| ip6 | Authorizes an IPv6 address or range | ip6:2001:db8::/32 | 0 |
| a | Matches the A/AAAA record of a domain | a or a:mail.example.com | 1 |
| mx | Matches the MX record servers | mx or mx:example.com | 1+ |
| ptr | Reverse DNS check (deprecated) | ptr:example.com | 1+ |
| exists | Checks if a domain has an A record | exists:%{i}._spf.example.com | 1 |
| all | Catch-all, matches everything | ~all or -all | 0 |
Common Syntax Mistakes
Missing v=spf1. Every SPF record must start with v=spf1. Without it, mail servers will not recognize the TXT record as SPF.
Multiple SPF records. You can only have one SPF record per domain. If you need to authorize multiple services, combine them into a single record. Need help building one? SPF Creator can generate the correct syntax for you.
Using commas or semicolons. SPF mechanisms are separated by spaces, not commas or semicolons. include:a.com,include:b.com is wrong. include:a.com include:b.com is correct.
Putting all in the wrong place. The all mechanism must be the last item in the record. Anything after all is ignored.
Exceeding the 10 DNS lookup limit. Mechanisms like include, a, mx, and exists each require DNS lookups. Per RFC 7208, Section 4.6.4, you get a maximum of 10. Going over causes a PermError and your SPF fails entirely. Read more about the 10 DNS lookup limit.
Putting It All Together
Here is a real-world example combining several mechanisms:
v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.5 ~all
This record authorizes Google Workspace and SendGrid via includes, plus a specific IP address, and soft fails everything else.
Once you understand these pieces, you can read any SPF record and know exactly what it does. For how SPF fits into the bigger picture, see our guide on SPF, DKIM, and DMARC explained, or check your DKIM and DMARC setup alongside your SPF.
References
- RFC 7208: Sender Policy Framework (SPF) — The current SPF specification, including all mechanism and modifier definitions
- RFC 7208, Section 4.6.4: DNS Lookup Limits — The 10 DNS lookup limit specification
Never miss an SPF issue
Monitor your SPF, DKIM, DMARC and MX records daily. Get alerts when something breaks.
Start Monitoring