SPF record syntax: every mechanism, qualifier and modifier explained
By TechCompare · Updated · How we check
The first matching term wins. List your senders first and end with ~all or -all, so mail from any other server gets a clear result.
An SPF record is one TXT record on your domain that starts with v=spf1 and lists the servers allowed to send mail for it. A receiver reads the terms from left to right and stops at the first one that matches the sending server. The sign in front of that term, like ~ or -, sets the result. If nothing matches, the result is neutral, which tells the receiver nothing at all.
How this is calculated
The terms that match a server are called mechanisms:
- ip4 and ip6 match an address or a range, like ip4:192.0.2.0/24. Without a /length they match one address.
- a matches the addresses in a name's A or AAAA records, and mx matches the addresses of a domain's mail servers. Both check your own domain unless you name another, like a:mail.example.com.
- include runs the SPF check of another domain, usually your email provider's, and matches when that check passes.
- exists matches when a name has an A record. It's mostly used with macros, which build the name from details of the message.
- ptr matches on the server's reverse DNS name. RFC 7208 says not to use it, because it's slow and unreliable.
- all matches every server, so it goes last.
Each mechanism can carry a qualifier that sets the result when it matches: a plus sign (+) for pass, a minus sign (-) for fail, a tilde (~) for softfail and a question mark (?) for neutral. A term without one passes, so include:_spf.google.com means the same as +include:_spf.google.com. That's why most records only show a qualifier on all. ~all says mail from other servers probably isn't yours. -all says it isn't.
include trips people up. It doesn't paste the other record into yours. It runs that record as a separate check and only uses the answer: a pass counts as a match, and a fail or softfail just moves on to your next term. If the included domain has no SPF record at all, the whole check stops with a permanent error.
Two modifiers change how the check runs. redirect= hands the whole check to another domain's record, which helps when many domains share one policy. Receivers ignore it when the record has an all term anywhere. exp= points at a TXT record with a message a receiver may show when mail fails. Each one may appear only once, and receivers skip modifiers they don't know.
Some terms cost a DNS lookup: include, a, mx, ptr, exists and redirect. A check gets 10 in total, counting the ones inside included records, while ip4, ip6 and all are free. Size matters as well. RFC 7208 suggests keeping the name plus all of its TXT records under 450 bytes, so the answer fits in one UDP packet.
The DNS Lookup explains each term of a domain's SPF record in a dropdown, follows every include and redirect, and counts the lookups.
Verdict
Start with v=spf1, add ip4 and ip6 ranges for servers you run, then one include per email service, and end with ~all while you're still finding every sender. Some receivers reject on -all before they check DKIM, which can block forwarded mail that DMARC would pass, so move to -all only if that trade suits you. Skip ptr, and keep one SPF record per domain.
More DNS scenarios
Related guides
Frequently asked questions
What's the difference between ~all and -all?
Does the order of terms in an SPF record matter?
What does +all do?
Related tools
Subnet Calculator
Calculate network address, broadcast address, and usable IP ranges for IPv4/IPv6.
Use toolText Encoding Converter
Convert text to Base64, binary, hex, URL encoding and HTML entities, and back again.
Use toolJWT Decoder & Validator
Decode JWT headers and claims, check exp, nbf and iat, and verify signatures locally with your own key.
Use tool