EmailAudit.io
All articles
Email Authentication14 min read·EmailAudit.io Security Team

SPF Record Syntax: Complete Guide

A complete SPF record syntax reference: the version tag, every mechanism, qualifiers, redirect and exp, evaluation order, macros, length limits and common errors.

The short answer: An SPF record is a single DNS TXT record that starts with v=spf1, followed by space-separated terms: mechanisms (ip4, ip6, a, mx, include, exists, all) that name authorized senders, optional qualifiers (+, -, ~, ?) that set the result, and optional modifiers (redirect, exp). Terms are evaluated left to right and the first match wins. The rules come from RFC 7208.

This page is a reference. If you only want a working record, the SPF generator builds one and the SPF checker validates it.


The Anatomy of an SPF Record

v=spf1 ip4:203.0.113.0/24 include:_spf.google.com include:servers.mcsv.net ~all
Part Role
v=spf1 Version tag. Must be the first term.
ip4:203.0.113.0/24 Mechanism: authorizes an IP range.
include:_spf.google.com Mechanism: authorizes whatever that domain's SPF record authorizes.
~all Mechanism with a qualifier: what to do with everything else.

Syntax rules that trip people up:

  • The record lives in a TXT record at the domain being checked (the root domain, or a subdomain if you send from one). It is not a separate "SPF" record type; that type was retired in RFC 7208.
  • Terms are separated by one or more spaces. Mechanism names and the v=spf1 tag are case-insensitive.
  • You may publish only one SPF record per domain name. Two records that begin with v=spf1 produce a permerror, and receivers treat that as a failure.

The Problem SPF Solves

Email was designed without any check on who is sending. SMTP lets a server claim to be sending from any address. Nothing in the original protocol stops a stranger from sending a message that says it comes from accounts@yourcompany.com.

SPF adds one verification: the domain owner publishes the list of servers that may send for it, and receivers check connecting servers against that list. A forged message sent from a server that is not on the list fails the check.

SPF does not encrypt anything, does not stop the content of a message from being malicious, and does not by itself decide what happens to a failure. It supplies a result that the receiver, and your DMARC policy, act upon.



Envelope sender versus the visible From address

This is the point that confuses almost everyone. A message has two sender identities:

Identity Also called Where it lives Who sees it
MAIL FROM Envelope sender, Return-Path, bounce address The SMTP conversation; saved as the Return-Path header Mostly invisible to recipients
From: Header From, visible From The message headers Shown in the mail client

SPF validates the first one only. A spammer can pass SPF using their own domain in MAIL FROM while the visible From: shows your brand. SPF alone never notices.

That is why DMARC exists. DMARC requires that the domain SPF authenticated (or the domain in a valid DKIM signature) matches the visible From: domain. This match is called alignment. Without it, a pass does not count for DMARC. The details are in SPF, DKIM and DMARC explained.

This also explains a common surprise: when you send through a marketing platform, MAIL FROM is often the platform's own bounce domain. SPF passes for the platform's domain, not yours, so it is unaligned for DMARC purposes, and DKIM must carry the DMARC pass instead.



How SPF Fits With DKIM and DMARC

The three standards check different things:

Standard Question it answers What it checks
SPF Is this server allowed to send for the envelope domain? Sending IP against DNS list
DKIM Was this message altered, and did the signing domain authorize it? Cryptographic signature in a header
DMARC Does an authenticated domain match the visible From, and what should happen if not? Alignment of SPF or DKIM, plus your policy

A sound setup uses all three. SPF covers the simple case of servers you control; DKIM survives forwarding; DMARC ties both to the From address people see and tells receivers to quarantine or reject failures. Start with a monitoring policy if you are new to this, as explained in DMARC policy: none, quarantine, reject.


Typical Records for Common Setups

Setup Example record
Google Workspace only v=spf1 include:_spf.google.com ~all
Microsoft 365 only v=spf1 include:spf.protection.outlook.com ~all
Microsoft 365 plus a marketing tool v=spf1 include:spf.protection.outlook.com include:servers.mcsv.net ~all
Domain that never sends email v=spf1 -all

Always take the exact include value from your provider's current documentation, since vendors occasionally change them. The adding third-party senders guide walks through that process.

Domains that never send mail deserve the last record in the table. Without it, attackers can spoof parked domains and lookalike subdomains freely.


Common Beginner Mistakes

  • Publishing a second record when adding a new tool, instead of editing the existing one.
  • Forgetting a sender, such as an invoicing system or website contact form, so its mail fails SPF.
  • Leaving old vendors in the record, which wastes lookups and authorizes services you no longer use.
  • Assuming SPF is the whole job. Passing SPF with a vendor's bounce domain does nothing for DMARC alignment.
  • Never checking again. Records drift as teams add tools. Re-test after every change, and see the email deliverability checklist for a regular routine.

Gmail and Yahoo now expect SPF and DKIM from anyone sending in volume; the specifics are in Google and Yahoo bulk sender requirements.



How to Set Up and Check Yours

  1. List every service that sends email as your domain: your mailbox provider, marketing tools, billing system, helpdesk, website forms.
  2. Build a single record with the SPF generator.
  3. Publish it as one TXT record at your domain's root.
  4. Test it with the SPF checker, which shows lookup counts and any errors.
  5. Send a test email and confirm spf=pass in the headers.
  6. Add DKIM and DMARC. The email security score shows what is missing.


The Version Tag

v=spf1 is the only valid version. It must appear at the very start of the TXT value, with no leading characters. A record such as " v=spf1 ..." with a stray leading space, or spf1 ... with the v= missing, is not recognized as SPF and the domain evaluates to none.


Qualifiers

A qualifier is a single character placed directly in front of a mechanism. It decides what result is returned if that mechanism matches.

Qualifier Name Result on match Typical use
+ Pass pass Default when no qualifier is written
- Fail fail (hard fail) -all to reject unlisted senders
~ SoftFail softfail ~all during rollout or as a long-term setting
? Neutral neutral ?all, effectively "no opinion"

include:example.net and +include:example.net mean the same thing. For help choosing between -all and ~all, see SPF hard fail vs soft fail.


Mechanisms

A mechanism describes a set of hosts. If the sending IP is in that set, the mechanism matches.

ip4 and ip6

ip4:192.0.2.10
ip4:198.51.100.0/24
ip6:2001:db8:1234::/48

These compare the connecting IP address directly. They need no DNS lookup and cost nothing against the lookup limit. An ip4 address with no prefix means /32 (one host). ip6 without a prefix means /128.

a

a
a:mail.example.com
a:mail.example.com/24
a/24//64

Matches if the sending IP equals an A (or AAAA) record of the named domain. With no domain, it uses the domain being checked. The first CIDR is the IPv4 prefix and the second, after //, is the IPv6 prefix. Costs one DNS lookup.

mx

mx
mx:example.org

Matches if the sending IP is an address of one of the domain's MX hosts. Useful only when your inbound servers also send your mail. It costs one lookup for the MX query, plus one for each MX hostname resolved (up to 10 names; more than that is a permerror).

include

include:_spf.google.com

Evaluates another domain's SPF record. If that record returns pass, the include matches and the qualifier applies. If the inner result is anything else (fail, softfail, neutral), the include simply does not match and evaluation continues with the next term. An inner -all does not fail your mail. If the included domain has no SPF record at all, the result is permerror. Each include is one lookup, plus all lookups inside the included record. See adding third-party senders to SPF for the vendor-by-vendor details.

exists

exists:%{i}._spf.example.com

Matches if the named domain resolves to any A record (the value is ignored). Almost always combined with macros to build per-IP lookups.

ptr

ptr:example.com

Performs a reverse lookup on the sending IP and checks the resulting names. RFC 7208 says senders should not use it: it is slow, unreliable and loads the receiver's DNS. Do not publish it.

all

-all
~all
?all
+all

Always matches. It goes last, because anything written after all is never evaluated. Never publish +all: it authorizes every server on the internet to send as you.


Modifiers

Modifiers are written name=value and, unlike mechanisms, have no qualifier. Each may appear at most once.

redirect

v=spf1 redirect=_spf.example.com

Replaces the current record with the policy of another domain. It is evaluated only after every mechanism in the record has failed to match, and it is ignored if the record contains an all mechanism. If the target has no SPF record, the result is permerror.

redirect vs include: use include to add another party's senders to your own list. Use redirect when a whole domain should share one policy, for example many parked or secondary domains all pointing to one master record. The key behavior difference is that redirect adopts the target's final result, including its -all, while include only contributes matches.

exp

v=spf1 mx -all exp=explain._spf.example.com

Names a TXT record whose text is returned in the SMTP rejection message when the result is fail. Most domains skip it.

Unknown modifiers

Unknown modifier names are ignored. An unknown mechanism is a permerror.


Evaluation Order and Results

Receivers evaluate left to right and stop at the first match. The qualifier on that mechanism becomes the result. If nothing matches and there is no redirect, the result is neutral.

For a message sent from 198.51.100.7 against this record:

v=spf1 ip4:203.0.113.0/24 include:_spf.google.com -all
  1. ip4:203.0.113.0/24 does not contain the IP, so move on.
  2. include:_spf.google.com is evaluated; Google's ranges do not include it, so no match.
  3. -all matches everything, so the result is fail.

The possible results are pass, fail, softfail, neutral, none (no SPF record), temperror (a transient DNS problem) and permerror (the record is broken or over a limit).

Put all last. Lookup limits apply to what is actually evaluated.


Macros

Macros let one record adapt to the message being checked. They start with %{ and end with }.

Macro Expands to
%{i} Sending IP address
%{s} Sender (MAIL FROM) address
%{l} Local part of the sender
%{o} Domain of the sender
%{d} Domain currently being checked

For example, exists:%{i}._spf.example.com turns a connection from 192.0.2.5 into a lookup for 5.2.0.192._spf.example.com. Macros appear mainly in exists and exp; most small domains never need them.


Length Limits

255 characters per string

A DNS TXT record is made of one or more character-strings, and each is limited to 255 bytes. A long SPF record must be split into several quoted strings inside the same TXT record:

example.com. IN TXT "v=spf1 ip4:203.0.113.0/24 ip4:203.0.114.0/24 ip4:203.0.115.0/24 " "include:_spf.google.com include:servers.mcsv.net -all"

Receivers join the strings with no added space, so end the first string with a trailing space (or begin the next with one). Many DNS panels split automatically; if yours has one text box, paste the whole value and let it do so. Splitting into separate TXT records is wrong, because that creates two SPF records.

512 bytes for UDP

Classic DNS responses over UDP were limited to 512 bytes. Larger answers need EDNS0 or a retry over TCP, which most resolvers now handle, but RFC 7208 still advises keeping the whole TXT answer within that size. Longer records risk being dropped by restrictive networks, so aim for roughly 450 characters at most.

10 DNS lookups and 2 void lookups

The count covers include, a, mx, ptr, exists and redirect. More than 10 returns permerror. More than two lookups returning no data (NXDOMAIN or empty answers) also produce permerror. The full treatment is in SPF too many DNS lookups.


Annotated Examples

Google Workspace only:

v=spf1 include:_spf.google.com ~all

One include (Google's record adds its own lookups), soft fail for everyone else.

Microsoft 365 plus a marketing platform plus an office IP:

v=spf1 ip4:203.0.113.25 include:spf.protection.outlook.com include:servers.mcsv.net -all

The IP costs nothing, each include costs at least one lookup, and -all rejects any unlisted source.

A domain that does not send mail:

v=spf1 -all

Publish this on parked domains so spoofed mail fails immediately.


Syntax Errors and What They Cause

Mistake Example Effect
Two SPF records Two TXT values starting v=spf1 permerror
Missing or misspelled version v=spf 1 ... or spf1 ... No SPF record found (none)
Typo in mechanism name inlcude:_spf.google.com permerror
Space after colon include: _spf.google.com permerror
More than 10 lookups Many includes permerror
Include of a domain without SPF include:old-vendor.example permerror
all not last -all include:x.com Everything after all ignored
+all or no all v=spf1 include:x.com Open policy or neutral for strangers
Redirect with an all redirect=x.com ~all redirect ignored
Unbroken string over 255 bytes One huge quoted value Rejected by DNS host, or record fails to publish

With DMARC enforced, an SPF permerror can get legitimate mail rejected if DKIM does not align either.


How to Verify Your Syntax

  1. Paste your domain into the SPF checker. It shows the parsed record, the lookup count and any syntax errors.
  2. If you are building or rewriting a record, use the SPF generator so qualifiers and ordering are right the first time.
  3. Send a test message to a mailbox you control and read the Authentication-Results header with the email header analyzer. You should see spf=pass.

Frequently Asked Questions

What is the correct format of an SPF record?

It begins with v=spf1, followed by space-separated mechanisms such as ip4:, include: and mx, and normally ends with ~all or -all. It is published as a single TXT record at the domain.

What is the difference between ~all and -all?

-all tells receivers that unlisted servers are unauthorized and should fail. ~all marks them as suspicious but not outright failed. With DMARC enforced, the practical difference is small, since DMARC decides the final action.

Should I use include or redirect?

Use include to add third-party senders to your own record. Use redirect only when a domain has no senders of its own and should adopt another domain's policy entirely.

Can I have more than one SPF record?

No. Only one TXT record per domain name may start with v=spf1. Merge all senders into one record; two records cause a permerror.

How long can an SPF record be?

Each quoted string is limited to 255 bytes, but a record can contain several strings that receivers concatenate. Keep the full record comfortably under about 450 characters and under 10 DNS lookups.

Is the ptr mechanism still allowed?

It is still valid syntax but deprecated by RFC 7208 and should not be used. Replace it with explicit ip4, ip6 or include terms.

Where do I find my SPF record?

It is a TXT record in your domain's DNS zone, starting with v=spf1. Look it up with the SPF checker or by querying TXT records for your domain.

Do I need an SPF record if I only use Gmail or Microsoft 365?

Yes. Both providers give you an include to publish, and Gmail and Yahoo expect bulk senders to authenticate with SPF and DKIM. Without it, your mail is more likely to land in spam.

Does SPF stop spoofing on its own?

No. It checks the hidden envelope address and does not tell receivers what to do with failures. DMARC with an enforced policy closes that gap.

Why does SPF pass but DMARC fail?

Usually because SPF validated a different domain from the visible From address, such as a vendor's bounce domain. DMARC needs alignment, so DKIM signing with your own domain has to cover that sender.


Next step: Run your record through the SPF checker now, or request a free email audit if you want someone to review SPF, DKIM and DMARC together.

Is your domain protected?

Run a free Full Audit — check SPF, DKIM, DMARC, blacklists, and MTA-STS in seconds. Get a branded PDF report delivered to your inbox. No account required.