"Passes SPF but fails DMARC" — Causes & Fix

Your headers show spf=pass and dmarc=fail on the same message. Nothing is broken in SPF — it authenticated a domain that is not the one in your From address.


Seeing spf=pass and dmarc=fail in the same Authentication-Results header looks like a contradiction. It is not. SPF checks the envelope sender — the Return-Path address, which recipients never see — while DMARC additionally requires that whatever authenticated aligns with the domain in the visible From: header. SPF passed for your sending platform's bounce domain. Your From: says your domain. Those are two different domains, so DMARC correctly refuses to count the pass.

What You Are Seeing

text
Authentication-Results: mx.google.com; spf=pass (google.com: domain of bounce-8842@mail.vendor.example designates 198.51.100.24 as permitted sender) smtp.mailfrom=bounce-8842@mail.vendor.example; dkim=pass header.i=@vendor.example header.s=k1; dmarc=fail (p=REJECT sp=REJECT dis=REJECT) header.from=example.com

Read the three domains rather than the three results. smtp.mailfrom is mail.vendor.example. header.i — the DKIM signing domain — is vendor.example. But header.from is example.com. Two green passes, both for a domain that is not yours, so DMARC fails and p=reject discards the message.

In an aggregate report the same situation appears as auth_results and policy_evaluated disagreeing:

xml
<policy_evaluated> <disposition>reject</disposition> <dkim>fail</dkim> <- DMARC-aligned result <spf>fail</spf> <- DMARC-aligned result </policy_evaluated> ... <auth_results> <spf> <domain>mail.vendor.example</domain> <result>pass</result> <- raw SPF result: genuinely passed </spf> </auth_results>

Both blocks are correct. The first reports alignment, the second reports raw mechanism results.

Paste a message into the Email Header Analyzer

Why SPF Passing Is Not Enough

SPF answers "is this IP allowed to send for the envelope domain?" It never looks at the From: header. That gap is exactly what DMARC was created to close — without an alignment requirement, an attacker could publish a valid SPF record for their own domain, pass SPF legitimately, and still put your address in From:.

So DMARC passes only if at least one of these holds:

  • SPF passed and the Return-Path domain aligns with the From domain, or
  • DKIM verified and the d= domain aligns with the From domain.

Under the default relaxed alignment, aligning means sharing an organizational domain — so bounce.example.com aligns with example.com, but mail.vendor.example does not. Full detail in DMARC Alignment Explained.

Why It Happens

1. Your ESP uses its own bounce domain

By far the most common cause. Mailchimp, SendGrid, HubSpot, Zendesk, Amazon SES and most others default to an envelope sender on their domain so bounces return to their infrastructure:

text
Return-Path: <bounce-8842@mail.vendor.example> SPF passes for vendor.example From: <news@example.com> DMARC SPF alignment FAILS

2. DKIM is signed with the vendor's key

If DKIM is also signing as d=vendor.example, both mechanisms are unaligned and there is nothing left to carry DMARC. This is the situation in the header example above, and it is why the message dies despite two passes.

3. The message was forwarded

A forwarding server rewrites the envelope sender to its own address so bounces come back to it. SPF then evaluates the forwarder's domain — often passing — while alignment is lost. Nothing you configure on the sending side prevents this; only aligned DKIM survives a forward.

4. Strict alignment is enabled

With aspf=s, a Return-Path of bounce.example.com no longer aligns with a From of example.com, even though both are yours. Strict mode breaks subdomain-based senders that relaxed mode handles fine:

text
v=DMARC1; p=reject; aspf=s # bounce.example.com no longer aligns with example.com v=DMARC1; p=reject # relaxed default — it aligns

5. Two different domains for brand reasons

Sending as example.com while all infrastructure authenticates as examplemail.net. No alignment mode bridges two separate organizational domains — either the From domain changes, or that domain has to sign.

How to Diagnose It

You need three values from one real message. Send a test to a mailbox you control, view the original source, and extract:

bash
# From a saved .eml file grep -iE '^(Return-Path|From|DKIM-Signature|Authentication-Results)' message.eml # Just the DKIM signing domain grep -io 'd=[a-z0-9.-]*' message.eml

Then compare them:

ValueWhere it comes fromMust align with From?
Return-PathEnvelope sender, checked by SPFYes, for SPF alignment
d= in DKIM-SignatureDKIM signing domainYes, for DKIM alignment
From:Visible senderIt is the reference

If neither of the first two shares an organizational domain with the third, you have found your problem. Across many senders at once, the DMARC Report Analyzer shows the same comparison per source.

How to Fix It

Fix DKIM alignment first

Aligned DKIM survives forwarding, making it the durable fix. Nearly every platform supports signing as your domain — it is usually called DKIM authentication, domain authentication, or sender verification in their UI, and it works by delegating selectors to them via CNAME:

text
s1._domainkey.example.com. IN CNAME s1.domainkey.uXXXX.vendor.example. s2._domainkey.example.com. IN CNAME s2.domainkey.uXXXX.vendor.example. # Verify the key resolves through the delegation dig +short TXT s1._domainkey.example.com

Once enabled, the signature changes to d=example.com and aligns. Send a fresh test — cached or queued mail will still show the old signature.

Then fix SPF alignment with a custom return path

Look for "custom return path", "custom bounce domain", "dedicated sending domain" or "remove via" in your platform's settings. It moves the envelope sender onto a subdomain you own:

text
# Vendor gives you a CNAME to publish em.example.com. IN CNAME bounce.vendor.example. # Result — envelope sender moves onto your domain Return-Path: <bounce-8842@em.example.com> SPF passes AND aligns
The "via" label is the visible symptomWhen Gmail shows "news@example.com via mail.vendor.example", it is telling you the envelope domain differs from the From domain — the exact mismatch causing your alignment failure. Configuring a custom return path removes the label and fixes the alignment at the same time.

Remove strict alignment if you set it

If your record contains aspf=s or adkim=s and you cannot articulate why, remove them. Relaxed is the default and blocks every unrelated domain just as effectively:

text
v=DMARC1; p=reject; rua=mailto:dmarc@example.com
Do not fix this by weakening DMARCDropping to p=none makes the bounces stop because nothing is enforced any more — the mail is still unauthenticated and your domain is unprotected. Use p=none as a temporary rollback while you fix alignment, never as the resolution.

Verify the Fix

text
# Send a fresh test through the affected platform, then check the headers: Authentication-Results: mx.google.com; spf=pass smtp.mailfrom=bounce-8842@em.example.com; <- your subdomain dkim=pass header.i=@example.com header.s=s1; <- your domain dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com

dmarc=pass with dis=NONE is the target: DMARC passed, no punitive disposition applied. Confirm in aggregate reports a day or two later that the source now shows an aligned pass at volume, not just for your one test message.

Frequently Asked Questions

How can SPF pass and DMARC fail at the same time?

Because they check different things. SPF authorises the sending IP for the envelope domain, and passes when that is correct. DMARC then asks whether the domain SPF authenticated matches the one in your From: header. When mail goes through a platform using its own bounce domain, SPF genuinely passes for the platform and DMARC correctly reports no alignment.

Do I need to change my SPF record?

Usually not. The include: for your platform is already correct — SPF is passing. The problem is which domain it passes for, which is fixed on the platform side by enabling a custom return path, not by editing your SPF record.

Why does this happen only on forwarded mail?

The forwarder rewrites the envelope sender to its own address, so SPF evaluates the forwarder's domain and alignment is lost. Nothing on your side prevents it. An aligned DKIM signature travels with the message and keeps DMARC passing through the forward.

My DKIM says pass — why does DMARC still fail?

Check the d= value in the signature. A signature can verify perfectly while being signed by your vendor rather than by you, and DMARC only counts a signature whose d= aligns with your From domain.

Should I use strict or relaxed alignment?

Relaxed, which is the default. Strict adds essentially no security — relaxed already blocks every unrelated domain — while breaking legitimate subdomain senders. If your record has aspf=s or adkim=s and you did not add them deliberately, remove them.

How long before the fix takes effect?

As soon as DNS propagates and the platform picks up the new configuration — typically minutes to a few hours. Send a fresh test rather than re-checking an old message, since queued mail still carries the previous headers.

Related