Skip to content

SPF (Sender Policy Framework) ​

SPF is an email authentication protocol that specifies which mail servers are authorized to send email on behalf of your domain.

How SPF Works ​

The Problem ​

Without SPF, anyone can send email claiming to be from your domain. There's no way for receiving servers to know if the sender is legitimate.

The Solution ​

SPF allows you to publish a list of authorized senders in DNS:

example.com.  TXT  "v=spf1 include:_spf.google.com -all"

When a receiving server gets an email "from" your domain:

  1. It looks up your SPF record in DNS
  2. It checks if the sending server is authorized
  3. It passes or fails the email based on your policy

SPF Record Syntax ​

An SPF record consists of:

v=spf1 [mechanisms] [all-policy]

Version Tag ​

Always starts with v=spf1 (required).

Mechanisms ​

Mechanisms define who is authorized to send:

MechanismDescriptionExample
ip4:IPv4 address or rangeip4:192.0.2.0/24
ip6:IPv6 address or rangeip6:2001:db8::/32
aAddresses in the domain's A/AAAA recordsa or a:mail.example.com
mxAddresses of the domain's MX hostsmx or mx:example.com
include:Checks another domain's SPF recordinclude:_spf.google.com
exists:Passes if a DNS name existsexists:%{i}._spf.example.com
ptrReverse DNS match. Deprecated: don't use itptr

SPF also has two modifiers:

ModifierDescriptionExample
redirect=Use another domain's SPF record instead. Ignored if the record has an all mechanismredirect=_spf.example.com
exp=Explanation text for rejected sendersexp=explain._spf.example.com

Qualifiers ​

Mechanisms can have qualifiers:

QualifierMeaningResult
+Pass (default)Authorized
-FailNot authorized
~SoftFailProbably not authorized
?NeutralNo opinion

All Policy ​

The all mechanism at the end defines the default policy:

PolicyMeaningRecommendation
-allFail: senders not listed aren't authorizedRecommended once your record is complete
~allSoft fail: probably not authorized, usually acceptedA step while you confirm your senders
?allNeutral: no statementNot recommended
+allPass: anyone may sendNever use this

Example Records ​

Basic - Google Workspace Only ​

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

Multiple Services ​

v=spf1 include:_spf.google.com include:_spf.salesforce.com include:mail.zendesk.com -all

Own Mail Server + Services ​

v=spf1 mx ip4:203.0.113.0/24 include:_spf.google.com -all

The Include Tree ​

When SPF uses include:, the included domain's SPF is evaluated recursively. This creates an "include tree":

example.com
└── include:_spf.google.com
    ├── include:_netblocks.google.com
    │   └── ip4:35.190.247.0/24 (and more)
    ├── include:_netblocks2.google.com
    │   └── ip4:64.18.0.0/20 (and more)
    └── include:_netblocks3.google.com
        └── ip4:66.102.0.0/20 (and more)

MailShield visualizes this tree to help you understand your SPF configuration.

DNS Lookup Limit ​

SPF is limited to 10 DNS lookups per check (RFC 7208, section 4.6.4), counted across all nested includes. Going over the limit makes SPF return permerror, which DMARC treats as a fail.

These count as DNS lookups:

  • include:
  • a
  • mx
  • ptr
  • exists:
  • redirect=

These don't:

  • ip4: and ip6:
  • all

Void Lookups ​

A lookup that returns no records (the name doesn't exist, or has no records of that type) is a void lookup. RFC 7208 tells receivers to allow at most 2 per check; after that, SPF returns permerror too. Void lookups usually come from includes of services you no longer use, or typos in host names.

Avoiding the Limits ​

  1. Remove unused includes, and audit them regularly
  2. Use IP ranges instead of host names for your own servers
  3. Move services to subdomains with their own SPF records
  4. Flatten with care: replacing includes with IP ranges works, but breaks when a provider changes its IPs

Common Issues ​

Too Many DNS Lookups ​

Problem: The record needs more than 10 DNS lookups.

Symptoms:

  • SPF returns permerror for every message, which DMARC counts as a fail
  • Mail fails DMARC unless DKIM passes and aligns

Solutions:

  • Remove unused includes and mechanisms
  • Move some services to a subdomain
  • Flatten includes to IP ranges, and keep them up to date

Multiple SPF Records ​

Problem: More than one TXT record at the domain starts with v=spf1.

Symptoms:

Solution:

  • Merge everything into a single record
  • Delete the duplicates

Record Too Long ​

Problem: A single TXT string can hold at most 255 characters.

Solution:

  • Split a longer record into several quoted strings in the same TXT record. Receivers join them without spaces, so split between mechanisms and keep the spaces: "v=spf1 include:_spf.google.com " "include:sendgrid.net -all"
  • Keep the whole record short: RFC 7208 recommends that the DNS answer fits in 512 bytes, so it doesn't need a fallback to TCP

Syntax Errors ​

Problem: Invalid SPF syntax.

Common mistakes:

  • Missing v=spf1
  • Typos in mechanism names
  • Invalid IP ranges

Solution:

  • Validate with MailShield or other tools

No All Mechanism ​

Problem: Record doesn't end with all.

Impact:

  • Neutral result for unauthorized senders
  • Reduced protection

Solution:

  • Add -all or ~all at the end

SPF and Email Forwarding ​

SPF can break when email is forwarded because:

  1. Original sender passes SPF
  2. Email is forwarded by another server
  3. Forwarding server's IP isn't in sender's SPF
  4. SPF fails at final destination

Solutions:

  • Rely on DKIM: an aligned DKIM signature usually survives forwarding, and DMARC passes when DKIM passes
  • Forwarders can use SRS (Sender Rewriting Scheme) so SPF checks their own domain
  • Some receivers accept ARC (Authenticated Received Chain) results from trusted forwarders

Changing DMARC alignment doesn't help here: the forwarding server isn't in your SPF record, whatever the alignment mode.

SPF Alignment for DMARC ​

For DMARC, SPF must "align" with the From header:

Relaxed alignment (default):

  • Envelope domain can be a subdomain of From header domain
  • mail.example.com aligns with example.com

Strict alignment:

  • Domains must match exactly

Best Practices ​

Do ​

✅ Use -all for hard fail in production
✅ Test with ~all before enforcing
✅ Monitor DNS lookup count
✅ Include all legitimate sending services
✅ Audit and remove unused includes regularly

Don't ​

❌ Use +all (allows everyone)
❌ Use deprecated ptr mechanism
❌ Exceed 10 DNS lookups
❌ Have multiple SPF records
❌ Forget about third-party senders \

Testing Your SPF ​

With MailShield ​

  1. Add your domain to MailShield.
  2. Open Checks → SPF to see the record, the include tree and the DNS lookup count.
  3. For any domain, including ones you don't monitor, use the SPF Checker.

Manual Testing ​

bash
# Look up SPF record
dig +short TXT example.com | grep spf

# Check from command line
nslookup -type=txt example.com

Provider Includes ​

The SPF includes for common providers, and the ones that don't need an include at all, are listed in Third-Party Senders.

Monitor and secure your email domains.