Sender Policy Framework (SPF), standardized under RFC 7208, provides the foundation of email authentication by allowing domain owners to declare which IP addresses are authorized to send mail using their identity in the SMTP envelope (MAIL FROM). This guide covers SPF record syntax, the notorious 10 DNS lookup limit, flattening vs. macro solutions, and alignment under DMARC.
In This Technical Guide
How SPF Operates in the SMTP Transaction
Sender Policy Framework (RFC 7208) evaluates authentication at the earliest phase of the SMTP dialogue. When an outbound Mail Transfer Agent (MTA) connects to a recipient’s MX server, it issues the MAIL FROM: command, transmitting the return-path envelope address (e.g., bounces@send.example.com).
The receiving mail server extracts the domain portion from that envelope address and executes a DNS TXT query for that domain. If a valid SPF record starting with v=spf1 is present, the receiver compares the connecting client’s IPv4 or IPv6 address against the authorized mechanisms declared in the record.
Crucially, SPF authenticates the envelope sender, NOT the human-readable From: header. If the envelope address is relay@thirdparty.com while the message body header displays From: ceo@yourcompany.com, classic SPF evaluates thirdparty.com. This is precisely why SPF must be paired with DMARC to secure the visible brand identity.
SPF Record Syntax & Mechanisms
An SPF record consists of the version string v=spf1 followed by an ordered list of mechanisms, qualifiers, and modifiers, evaluated from left to right:
v=spf1 ip4:198.51.100.0/24 ip4:203.0.113.15 include:_spf.google.com include:sendgrid.net ~all
| Mechanism | Counts Against 10-Lookup Limit? | Description & Example |
|---|---|---|
ip4: / ip6: |
No (0 Lookups) | Authorizes specific IPv4/IPv6 addresses or CIDR blocks. e.g., ip4:198.51.100.10 or ip4:198.51.100.0/24. Always prefer IP mechanisms for high efficiency. |
include: |
Yes (1 + Sub-lookups) | Recursively queries and evaluates the SPF record of another domain. e.g., include:_spf.google.com. |
a / a: |
Yes (1 Lookup) | Matches if the sending IP equals any A or AAAA record for the current domain or specified host. e.g., a:mail.example.com. |
mx / mx: |
Yes (1 Lookup + MX resolution) | Resolves the domain’s MX records, then looks up their A records to match the sender IP. Costly; avoid in high-volume production. |
exists: |
Yes (1 Lookup) | Executes an A record query for a constructed hostname; passes if any address resolves. Often used with macro expansions. |
redirect= |
Yes (1 Lookup) | Hands over evaluation entirely to another domain’s SPF record. Replaces current record evaluation. |
all |
No (0 Lookups) | The terminal catch-all mechanism. Evaluates every sender that failed to match prior mechanisms. |
The 10 DNS Lookup Limit & PermError Trap
To prevent Denial-of-Service (DoS) amplification attacks against DNS infrastructure, RFC 7208 Section 4.6.4 strictly imposes that an SPF evaluation must not generate more than 10 DNS queries that resolve a, mx, include, ptr, or exists mechanisms.
If a receiving server encounters an 11th DNS query while traversing an SPF record (including all nested include: directives), evaluation terminates immediately with a fatal PermError (Permanent Error). Under DMARC, a PermError causes SPF to fail completely, potentially dropping legitimate mail to spam or outright rejecting it.
Overcoming the Limit: Flattening vs. Dynamic Macros
Modern enterprises utilizing multiple SaaS providers (Google Workspace, HubSpot, Marketo, Zendesk, Salesforce) rapidly exceed 10 DNS queries. Two operational methodologies solve this constraint:
Method 1: SPF Record Flattening
SPF Flattening queries all nested include: domains, resolves their underlying IP netblocks, and writes static ip4: and ip6: mechanisms directly into the root SPF record. Because IP mechanisms require zero DNS queries, this reduces lookup counts to zero.
The Risk: SaaS providers frequently change their sending IP pools without warning. Static flattening requires automated continuous polling (every 15–30 minutes) to update DNS records before providers route mail across newly provisioned IPs.
Method 2: Dedicated Subdomain Segregation (Recommended)
Rather than authorizing all corporate and transactional services on the root domain, delegate distinct sending domains:
corp.example.com→ Dedicated solely to Google Workspace / Microsoft 365 (1 lookup).news.example.com→ Dedicated to marketing automation (2 lookups).notify.example.com→ Dedicated to AutoSMTP high-throughput transactional bare-metal (0 lookups via dedicated IPs).
Qualifiers Decoded: HardFail (-all) vs. SoftFail (~all)
Every mechanism can be prefixed with one of four qualifiers determining the result when a match occurs:
-Fail (HardFail): e.g.,-all. Explicitly states that non-matching IPs are unauthorized. Historically intended for outright rejection by receiving MTAs.~SoftFail: e.g.,~all. Indicates that the sender is likely unauthorized, but receivers should accept the message and mark it with higher spam suspicion.?Neutral: No policy stated. Evaluates as neither pass nor fail.+Pass (Default): If no prefix is present,+is implied (e.g.,ip4:...is identical to+ip4:...).
The Modern Deliverability Reality: In a world governed by DMARC, ~all is widely recognized as industry best practice. When paired with DMARC (p=quarantine or p=reject), DMARC makes the ultimate policy decision, while ~all prevents legacy receivers from prematurely dropping mail that undergoes legitimate intermediate forwarding.
SPF Alignment with DMARC
For SPF to satisfy DMARC, the domain in the envelope MAIL FROM must align with the domain in the header From::
| Envelope MAIL FROM | Header From: | aspf=r (Relaxed) | aspf=s (Strict) |
|---|---|---|---|
bounces@example.com |
news@example.com |
PASS (Aligned) | PASS (Aligned) |
bounces@mta.example.com |
billing@example.com |
PASS (Aligned) | FAIL (Unaligned) |
bounces@esp-shared.com |
billing@example.com |
FAIL (Unaligned) | FAIL (Unaligned) |
Auditing & Troubleshooting SPF Failures
When debugging SPF rejections in production logs, inspect the Authentication-Results header inserted by the receiver:
Authentication-Results: mx.google.com; spf=pass (google.com: domain of bounces@mta.example.com designates 198.51.100.24 as permitted sender) smtp.mailfrom=bounces@mta.example.com; dmarc=pass (p=REJECT sp=REJECT dis=none) header.from=example.com
If the header reports spf=permerror, immediately verify lookup counts using command-line diagnostic tools:
dig TXT example.com +short
Turnkey Infrastructure Provisioned for Bulletproof Deliverability
Eliminate protocol configuration failures, manual DNS drift, and deliverability drops. AutoSMTP automates dedicated MTA deployment, IP ramp-ups, and live RFC compliance on unthrottled enterprise bare-metal.
Upgrade to Enterprise Dedicated Email Infrastructure
Deploy unthrottled bare-metal SMTP relay clusters with built-in warming, authentication, and 24/7 deliverability defense.
View Infrastructure Plans →