Why SPF passes but DMARC still fails
This is the single most common email authentication puzzle, and it catches people who have done everything the guides told them to. The SPF record is published. A test message passes SPF. DMARC still reports a failure, and mail starts landing in spam.
The reason is that SPF and DMARC do not check the same address.
Two different senders in every message
Every email carries two sender addresses, and only one of them is ever shown to the recipient.
- The envelope sender — given in the SMTP
MAIL FROMcommand and usually recorded in theReturn-Pathheader. Bounces go here. Nobody sees it unless they open the headers. - The header From — the
From:line, which is what the mail client displays and what a person actually reads.
SPF authenticates the first one. It answers a narrow question: was this
server permitted to send mail using that envelope domain? It says nothing at
all about the From: line.
That gap is the whole problem. A forger can put anything in From:,
use an envelope domain they legitimately control, and collect a clean SPF pass
on a message that appears to come from your bank.
What DMARC adds: alignment
DMARC closes the gap by requiring alignment. It is not enough for SPF
to pass; the domain SPF authenticated must also match the domain in the
From: header.
DMARC passes when either of these holds:
- SPF passes and the envelope domain aligns with the From domain, or
- DKIM verifies and the signing domain (the
d=tag) aligns with the From domain.
Only one needs to succeed. But each one needs both halves — a pass on its own is not sufficient, which is exactly the case people run into.
Alignment comes in two modes, set by aspf and adkim:
- Relaxed (the default): the organisational domains must match.
mail.example.comaligns withexample.com. - Strict: the domains must be identical.
mail.example.comdoes not align withexample.com.
The three situations that produce this
1. A marketing or ticketing platform sends on your behalf
This is by far the most frequent cause. You send a campaign from
[email protected], but the platform sets the envelope sender to
something like [email protected] so it can process bounces
itself.
SPF passes — against mail-provider.net. The From domain is
yourcompany.com. They do not align, so the SPF half of DMARC fails. If
the platform is not also DKIM-signing with your domain, DMARC fails outright.
The fix is on the platform's side: configure a custom return path (often
called a custom bounce domain or CNAME setup) on a subdomain of yours, and set
up DKIM signing with d=yourcompany.com. Both are standard features.
Adding the provider to your SPF record does not fix this — it was
never an SPF failure.
2. The message was forwarded
A mailing list or a personal forwarding rule resends your message from its own server. That server is not in your SPF record, so SPF now fails for the new hop. This is inherent to how forwarding works and cannot be fixed with SPF.
DKIM survives forwarding, because the signature travels with the message. This is the practical reason to sign with DKIM even if SPF already passes: it is the half of DMARC that keeps working when mail is relayed.
3. Subdomain mismatch under strict alignment
You publish aspf=s, then send from mail.example.com with a
From address at example.com. Under strict mode those are different
domains. Relaxed alignment — the default — would have accepted it.
How to tell which one you have
Look at the Authentication-Results header of a message that failed.
A useful one looks like this:
Authentication-Results: mx.example.net; spf=pass (sender IP is 198.51.100.7) [email protected]; dkim=pass header.d=mail-provider.net; dmarc=fail (p=none dis=none) header.from=yourcompany.com
Everything you need is there. SPF passed for
[email protected]. DKIM passed for
header.d=mail-provider.net. But header.from is
yourcompany.com, which matches neither. That is situation 1, and the
answer is a custom return path plus DKIM signing with your own domain.
If you have rua configured in your DMARC record, the aggregate reports
show the same thing across every sender at once, which is the fastest way to
find a platform you had forgotten was sending as you.
The order to fix things in
- Publish DMARC at
p=nonewith anruaaddress. This changes nothing about delivery and starts the reports flowing. - Read a few weeks of reports and list every source sending as your domain.
- For each legitimate one, get DKIM signing aligned to your domain. Fix the return path where the provider supports it.
- Only then move to
p=quarantine, and laterp=reject.
Going straight to p=reject without step 2 is how organisations
discover, painfully, which internal system had been sending invoices all
along.
One more thing worth checking
SPF has a hard limit of ten DNS lookups. Every include and
redirect counts, recursively. Go over it and the result is
permerror, which receivers treat as a failure — and it happens
silently, usually the day after someone adds one more vendor. It is worth
knowing your current count before it becomes an outage.
The Email DNS Lookup module reads your SPF, DKIM, DMARC, BIMI, MTA-STS and TLS-RPT records, counts the SPF lookups the way a receiver does, and reports the DKIM key size — free, with no account.