SPF and DMARC alignment
How SPF records and includes work, why SPF pass doesn't always mean DMARC pass, and SPF's limitations for forwarded mail.
SPF is a DNS record that lists which IP addresses are allowed to send email on behalf of your domain. Receivers check it before deciding whether to deliver, quarantine, or reject a message.
But SPF has a subtlety that catches most developers off guard: it checks the envelope sender, not the From address your recipients see. That gap is exactly why SPF pass doesn't always translate to DMARC pass.
How SPF records work
An SPF record is a TXT record at your domain apex. It looks like this:
v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.5 ~allBreaking this down:
v=spf1: required prefix identifying this as an SPF recordinclude:_spf.google.com: pull in Google's authorized IP listinclude:sendgrid.net: pull in SendGrid's authorized IP listip4:203.0.113.5: explicitly authorize this IP address~all: softfail everything else (most receivers treat this as a warning, not a hard fail)
Use -all instead of ~all if you want unauthorized IPs to fail outright. Never use +all; it authorizes every IP on the internet.
The 10-DNS-lookup limit
Every include:, a:, mx:, ptr:, and exists: mechanism costs one DNS lookup at evaluation time. The SPF spec hard-limits this to 10 (RFC 7208 §4.6.4). Direct IP entries (ip4:, ip6:) are free: they don't trigger a lookup.
This limit is easier to hit than it looks. Google Workspace, SendGrid, Mailchimp, and Postmark each consume at least one lookup, and those include: targets often chain to further includes. If the total exceeds 10, receivers return permerror, which most treat the same as a failure.
If you're seeing unexplained SPF failures in your DMARC aggregate reports, count your lookups including the transitive ones inside each include:. The SPF check tool will count them for you.
Envelope sender vs From header
Email has two different "from" fields that serve different purposes:
From header: what email clients display to recipients. This is you@yourdomain.com in the compose window.
Envelope sender (Return-Path): where bounce messages go. Set by the sending mail server, not visible to recipients. When you send through SendGrid, the Return-Path is something like bounces+abc123@em.yourdomain.sendgrid.net or bounces@sendgrid.net, depending on your configuration.
SPF checks the envelope sender domain, not the From header. The check asks: does this sending IP appear in the SPF record for the Return-Path domain?
This distinction matters for DMARC. DMARC requires the SPF-authenticated domain to align with your From header domain. If the two are different, SPF authenticates fine against the third-party domain, but DMARC alignment still fails because the domains don't match.
Why forwarding breaks SPF
When a recipient forwards your email to another address, the forwarding server re-sends the message from its own IP, but leaves the Return-Path pointing to your domain.
SPF checks that new IP against your domain's SPF record. The forwarding server's IP isn't listed, so SPF fails.
There's no fix for this. SPF has no way to recognize forwarded mail as legitimate; it only knows that an unlisted IP is sending on behalf of your domain. This is a protocol limitation, not a misconfiguration.
The practical takeaway: don't rely on SPF as your primary DMARC mechanism. DKIM signatures are embedded in the message headers and survive forwarding intact regardless of which server relays the message. If your sending services are DKIM-aligned, forwarded mail will still pass DMARC even when SPF fails.
Why SPF pass doesn't mean DMARC pass
For DMARC to pass via SPF, two conditions must both be true:
- SPF authentication: the sending IP is listed in the SPF record for the Return-Path domain
- SPF alignment: the Return-Path domain matches your From header domain (at the organizational domain level under relaxed alignment, or exactly under strict)
Most third-party email services use their own domain in the Return-Path by default. SPF authenticates successfully against their domain, but that domain doesn't match yours, so DMARC alignment fails even though SPF passed.
The fix is to configure a custom Return-Path (sometimes called a custom bounce domain or custom MAIL FROM) so the Return-Path domain matches your From domain. Most major ESPs support this. Without it, DMARC compliance for that service depends entirely on DKIM alignment.
In practice, treat SPF as a supporting signal rather than your primary DMARC mechanism. Get DKIM aligned for every sending service, and treat SPF alignment as a bonus when it's available.
See also: DKIM and DMARC alignment: why DKIM survives forwarding where SPF doesn't, and how to verify your DKIM setup.