Introduction
DMARC fails when SPF passes because SPF checks the envelope sender (Return-Path, or RFC5321.MailFrom) domain, while DMARC only counts that pass if the domain aligns with the visible From (RFC5322.From) domain. An SPF pass for an email service's bounce domain does not count. If DKIM is also missing or unaligned, DMARC fails.
It is a classic "but the record is fine" ticket in a DMARC project. Nothing is broken in DNS: SPF did its job, just for a domain that DMARC does not care about. This article is the troubleshooting answer for that one situation. For the general concept, see DMARC alignment explained: relaxed vs strict; for a record that is broken or missing, see why your DMARC record is not working. The protocol overview is in the DMARC guide.
Key takeaways
- DMARC needs an aligned pass: SPF must pass for a domain that shares the Organizational Domain with the From address (or matches it exactly under
aspf=s), or DKIM must pass with an alignedd=domain. - The usual cause is a third-party sender using its own Return-Path. The fix is a custom bounce domain under your domain, plus DKIM signed with your domain.
- Aggregate reports show the problem directly:
<auth_results><spf><result>sayspasswhile<policy_evaluated><spf>saysfail, and<auth_results><spf><domain>names the domain that actually passed. - Aligned DKIM is the durable fix, because it survives forwarding where SPF cannot.
- RFC 9989 determines the Organizational Domain with a DNS tree walk, not the Public Suffix List.
What does DMARC actually check after SPF passes?
DMARC takes the domain that SPF authenticated and compares it with the domain in the From header. Under RFC 9989, Section 5.3.5, a message passes DMARC only if at least one authenticated identifier (from SPF or DKIM) aligns with the Author Domain. An unaligned SPF pass contributes nothing to the result.
Two details in RFC 9989 matter here:
- Only the MAIL FROM identity counts. Section 4.4.2 says DMARC relies solely on SPF validation of the MAIL FROM identity. SPF can also check the HELO name (RFC 7208, Section 2.3), but a HELO pass is ignored by DMARC.
- Alignment has two modes, set with the
aspftag for SPF andadkimfor DKIM (Section 4.7). Relaxed (r, the default) requires the same Organizational Domain. Strict (s) requires an exact match.
Here is the pattern in an Authentication-Results header:
Return-Path: <bounces+12345@bounce.esp-mail.example>
From: "Example Ltd" <news@example.com>
Authentication-Results: mx.receiver.example;
spf=pass smtp.mailfrom=bounce.esp-mail.example;
dkim=pass header.d=esp-mail.example;
dmarc=fail (p=quarantine) header.from=example.com
SPF passed and DKIM passed, both for esp-mail.example. Neither aligns with example.com, so DMARC fails.
How does RFC 9989 decide what the Organizational Domain is?
RFC 9989 replaces the Public Suffix List with a DNS tree walk (Section 4.10). The receiver queries _dmarc records from the Author Domain upward, with at most eight queries. Section 4.10.2 then selects the Organizational Domain: a record with psd=n marks its own domain; a record with psd=y makes the domain one label below it the Organizational Domain; otherwise the record with the fewest labels wins.
In practice, for a normal client setup with a record at _dmarc.example.com, the Organizational Domain of mail.example.com is example.com, exactly as before. The difference shows up with unusual registry structures and with domains that publish psd=n to declare themselves an Organizational Domain. When you explain alignment to a client, use the RFC 9989 term "Organizational Domain" and drop references to the PSL: they describe the obsolete RFC 7489 method. RFC 9989 explained covers the wider changes.
Some worked pairs, assuming example.com publishes a DMARC record:
| Return-Path domain | From domain | aspf=r (relaxed) |
aspf=s (strict) |
|---|---|---|---|
example.com |
example.com |
Aligned | Aligned |
bounce.example.com |
example.com |
Aligned | Not aligned |
example.com |
news.example.com |
Aligned | Not aligned |
bounce.esp-mail.example |
example.com |
Not aligned | Not aligned |
example.co.uk |
example.com |
Not aligned | Not aligned |
The last row catches people out: two domains owned by the same client are still different Organizational Domains.
What are the common causes of SPF pass but DMARC fail?
Almost every case falls into one of six patterns. The first two account for most tickets in an MSP estate; the rest appear after migrations or changes to SPF records.
| Cause | What you see | Why DMARC fails |
|---|---|---|
| Third-party sender (ESP, CRM, helpdesk) using its own Return-Path | smtp.mailfrom=bounce.esp-mail.example |
SPF passed for the provider's domain, not yours |
| Forwarding and mailing lists | smtp.mailfrom=lists.example.org or a rewritten (SRS) address |
The forwarder or list passes SPF for its own domain; DKIM often breaks when the list edits the message |
SPF passing for a subdomain with aspf=s |
smtp.mailfrom=bounce.example.com, header.from=example.com |
Strict mode needs an exact match |
| SPF pass on HELO only | spf=pass smtp.helo=mta1.esp-mail.example |
DMARC ignores the HELO identity |
| SPF permerror (too many lookups) | spf=permerror on some messages, pass on others |
A permerror is not a pass; senders matched late in the record hit the 10-lookup limit |
DKIM missing or signed with the provider's d= |
dkim=none, or header.d=esp-mail.example |
Without aligned DKIM there is no second route to a pass |
Why does SPF "pass" for some messages and permerror for others?
RFC 7208, Section 4.6.4, limits SPF evaluation to 10 DNS-querying terms (include, a, mx, ptr, exists and redirect) and requires a permerror when the limit is exceeded. Evaluation stops at the first match, so a sender listed early can pass while one listed later breaches the limit. A spot check from the first sender looks fine; the aggregate report tells the real story. See SPF too many DNS lookups for the repair.
Why does a HELO pass mislead people?
Some tools and receivers record SPF for the HELO name as well. A header like this looks reassuring but proves nothing for DMARC:
Authentication-Results: mx.receiver.example;
spf=pass smtp.helo=mta1.esp-mail.example;
spf=pass smtp.mailfrom=bounce.esp-mail.example;
dmarc=fail header.from=example.com
Ignore smtp.helo. Only the smtp.mailfrom domain is used for DMARC, and here it is still the provider's.
How do you diagnose it from headers?
Read the receiving server's Authentication-Results header and compare three domains: smtp.mailfrom (SPF), header.d (DKIM) and header.from (the Author Domain). If neither of the first two aligns with the third, you have found the cause. Use the topmost header added by the final receiver, not one inserted by an earlier hop.
A practical routine:
- Get the full original headers of a failing message (in Outlook: message source; in Gmail: "Show original").
- Paste them into the email header analyzer to pull out the authentication results and the hop list.
- Note the Return-Path, the
d=value in eachDKIM-Signatureand the From domain. - Look up the client's DMARC record and check
aspfandadkim. A strict setting explains a subdomain mismatch immediately. - Check the SPF record with the SPF analyzer for lookup count and permerror risk.
If the message passed through a gateway or a forwarder, the last hop may not be the original sender. How to read email headers covers hop-by-hop reading.
How do you diagnose it from aggregate reports?
Aggregate reports show the problem without needing a sample message. In each record, <auth_results><spf> holds the raw SPF result and the domain it was evaluated for, while <policy_evaluated><spf> holds the DMARC verdict after alignment. A raw pass next to an evaluated fail is the SPF-pass-DMARC-fail signature.
RFC 9990 defines the format (Section 3.1.1 and the schema in Appendix A). A trimmed record:
<record>
<row>
<source_ip>192.0.2.25</source_ip>
<count>418</count>
<policy_evaluated>
<disposition>quarantine</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>esp-mail.example</domain>
<selector>s1</selector>
<result>pass</result>
</dkim>
<spf>
<domain>bounce.esp-mail.example</domain>
<scope>mfrom</scope>
<result>pass</result>
</spf>
</auth_results>
</record>
Read it like this: 418 messages from 192.0.2.25 claimed example.com. SPF passed for bounce.esp-mail.example and DKIM passed for esp-mail.example, but policy_evaluated shows both as fail because neither aligns. Note that RFC 9990 allows only mfrom as the SPF scope, matching RFC 9989's MAIL FROM rule. For the full field walkthrough, see DMARC aggregate reports explained.
The source IP and the <auth_results> domains usually identify the sending service. Group records by those domains, not by IP, because providers send from large and changing IP ranges.
How do you fix each cause?
Fix alignment at the sender, not in your SPF record. Adding the provider's include: to your SPF does nothing when SPF is already passing for the provider's own domain. The two durable fixes are a custom Return-Path under your domain and DKIM signed with your domain.
- Third-party sender: configure a custom bounce or Return-Path domain in the provider's settings. This is usually a CNAME such as
bounce.example.compointing to a host the provider names, so SPF passes forbounce.example.com, which aligns withexample.comunder relaxed mode. Then enable custom DKIM so the provider signs withd=example.com. How to handle third-party senders covers the onboarding conversation. - Strict SPF alignment on a subdomain: change
aspf=sto the default relaxed mode unless the client has a documented reason for strict, or make the Return-Path domain match the From domain exactly. - HELO-only pass: treat it as no SPF pass at all, and fix the MAIL FROM domain as for a third-party sender.
- Permerror: reduce the SPF record below 10 lookups by removing unused includes and moving bulk senders to their own subdomain.
- DKIM missing or provider-signed: publish the provider's selector records under your domain and confirm the signature carries your
d=value (RFC 6376, Section 3.5 definesd=as the signing domain). Check it with the DKIM validator. - Forwarding and mailing lists: you cannot fix the forwarder's SPF. Aligned DKIM survives plain forwarding because the signature travels with the message. Where a list modifies the message, receivers can rely on ARC (RFC 8617, Experimental) to see the original results; see ARC explained.
After the fix, the header should look like this:
Return-Path: <bounces+12345@bounce.example.com>
From: "Example Ltd" <news@example.com>
Authentication-Results: mx.receiver.example;
spf=pass smtp.mailfrom=bounce.example.com;
dkim=pass header.d=example.com;
dmarc=pass header.from=example.com
One aligned pass is enough for DMARC, but aim for both. SPF alignment breaks on forwarding; DKIM alignment breaks if a key is lost or a provider changes its setup. Two routes give you margin before p=reject.
How should an MSP triage this across a client portfolio?
Treat SPF-pass-DMARC-fail as a portfolio pattern, not a single ticket. The same ESP or CRM is usually misconfigured at several clients, so one fix procedure can close many failures. Work from aggregate data first and only ask for sample messages when the report does not identify the sender.
A weekly routine that scales:
- Filter every client's aggregate data for records where
<auth_results><spf><result>ispassand<policy_evaluated><spf>isfail. - Group by the
<auth_results><spf><domain>value across all clients. A provider bounce domain that appears at many clients is one playbook, not many tickets. - Rank by message volume and by each client's policy. A failing source at a
p=rejectclient loses mail today; atp=noneit blocks the next policy step. - Classify each group with the cause table above: provider Return-Path, forwarding, strict alignment, permerror or DKIM.
- Apply the matching fix through change control, with the client's approval for any DNS change. DMARC change management for MSP portfolios describes the process.
- Verify in the next reports that
policy_evaluatednow showspassfor that source before you advance the client's policy.
Forwarding failures need a different conversation: they are often recipients forwarding mail elsewhere, not a sender you control. Make sure aligned DKIM is in place, then accept a small residual failure rate rather than chasing it.
DMARC AI is a multi-tenant platform for MSPs that processes aggregate reports across client domains, so this kind of cross-client grouping is the workflow it supports; see DMARC for MSPs.
Frequently asked questions
Can DMARC pass if SPF fails?
Yes. DMARC needs only one aligned pass. If DKIM passes with a d= domain that aligns with the From domain, DMARC passes even when SPF fails or passes for an unaligned domain. That is why aligned DKIM is the most reliable route, particularly for mail that may be forwarded.
Does adding the ESP to my SPF record fix DMARC?
Usually not. If the provider uses its own Return-Path, SPF is evaluated against the provider's domain, not yours, so your SPF record is never consulted. The fix is a custom Return-Path under your domain, aligned DKIM, or both. Unneeded includes also push you towards the 10-lookup limit.
Should I use strict or relaxed SPF alignment?
Relaxed, for almost every client. RFC 9989 makes relaxed the default and notes that nearly all Domain Owners find it sufficient. Strict alignment breaks common setups where the Return-Path is a subdomain such as bounce.example.com. Use strict only with a documented reason and full knowledge of every sender.
Why do aggregate reports show SPF pass and DMARC fail for the same source?
The report holds two SPF results. <auth_results><spf> is the raw SPF check for the domain named in its <domain> element. <policy_evaluated><spf> is the result after alignment against the From domain. Raw pass plus evaluated fail means SPF passed for a domain that does not align.
Does forwarding always break DMARC?
No. Forwarding usually breaks SPF, because the forwarder's IP is not in the sender's SPF record or the forwarder rewrites the Return-Path. A DKIM signature survives as long as the forwarder does not modify the signed content, so mail with aligned DKIM normally still passes DMARC after forwarding. The DMARC and email forwarding guide covers which forwarding setups modify messages and how to spot them in reports.