Home Blog Contact
Home/Blog/How to Diagnose DMARC Alignment Failing Per R…
How toEmail MarketingDMARCEmail DeliverabilityAlignment

How to Diagnose DMARC Alignment Failing Per Recipient

9 min readBy Miloš Mitrović

When DMARC passes for most of your list but fails for a stubborn slice of recipients, the cause is almost never your SPF or DKIM keys. It is identifier alignment: the receiving provider authenticated a domain that does not match the domain in the visible From header, and different providers evaluate that match differently. The one-line answer: read your aggregate (RUA) reports record by record, compare the raw result in auth_results against the aligned verdict in policy_evaluated, and the split will point at a strict alignment mode, a forwarder, or a stale DNS cache.

Key takeaways

  • A per-recipient DMARC split is an alignment problem, not an authentication problem: your keys are valid, but the authenticated domain does not tie back to the From domain for every receiver.
  • DMARC passes when either SPF or DKIM both authenticates and aligns, so you only need one aligned identifier, per the Google Workspace DMARC requirements.
  • The single most useful move is comparing auth_results (raw pass or fail) with policy_evaluated (the aligned verdict) in the same RUA record.
  • Relaxed alignment is the default and matches at the organizational-domain level, so aspf=s or adkim=s quietly breaks subdomain senders.
  • Forwarding and mailing lists rewrite the envelope, which fails SPF alignment while a body-signed DKIM survives, so the failing recipients cluster around forwarders.
  • DNS TTL and caching mean a record change propagates unevenly, producing a genuine pass-for-some, fail-for-others window that resolves on its own.

What you need

  • Edit or at least read access to the DNS zone for the From domain, so you can inspect the _dmarc TXT record.
  • A DMARC record already publishing a rua= address to an inbox or aggregator whose reports you can open. Without RUA you are blind to the recipient split.
  • A way to parse XML: a text editor, xmllint, a short script, or a report analyzer.
  • The exact envelope (Return-Path) domain and the DKIM d= domain your ESP signs with. In Klaviyo or a similar platform these are set when you configure a dedicated sending domain.

How to isolate which recipients fail DMARC alignment

  1. Confirm reporting is on and read your published policy. Alignment modes live in the same record:
    dig +short TXT _dmarc.example.com
    # v=DMARC1; p=none; rua=mailto:[email protected]; adkim=r; aspf=r
    Note the adkim and aspf values. If they are absent, both default to relaxed (r).
  2. Collect at least seven days of aggregate reports. Each report is one XML file per receiving provider per day. Do not judge a split off a single report; providers batch on different schedules.
  3. For every <record>, extract five fields: source_ip, identifiers/header_from (the domain the recipient saw), policy_evaluated/spf and policy_evaluated/dkim (the aligned verdicts), and auth_results (the raw checks). A short parser does this cleanly:
    import glob, xml.etree.ElementTree as ET
    for f in glob.glob("reports/*.xml"):
        root = ET.parse(f).getroot()
        org = root.findtext("report_metadata/org_name")
        for r in root.findall("record"):
            yield {
              "provider": org,
              "source_ip": r.findtext("row/source_ip"),
              "count": r.findtext("row/count"),
              "header_from": r.findtext("identifiers/header_from"),
              "eval_spf": r.findtext("row/policy_evaluated/spf"),
              "eval_dkim": r.findtext("row/policy_evaluated/dkim"),
              "auth_spf": r.findtext("auth_results/spf/result"),
              "auth_dkim": r.findtext("auth_results/dkim/result"),
              "dkim_d": r.findtext("auth_results/dkim/domain"),
            }
    The element names above are the ones defined in the aggregate report schema of RFC 7489.
  4. Group the parsed rows by provider and header_from. A per-recipient alignment split looks like this: the same header_from, with eval_spf or eval_dkim reading pass for some providers or source IPs and fail for others in the same window.
  5. Separate authentication from alignment for the failing rows. If auth_spf is pass but eval_spf is fail, SPF authenticated but did not align. The distinction between the raw check and the aligned verdict is exactly what these two blocks encode, as EasyDMARC's guide to reading aggregate reports lays out.
  6. Check your alignment mode against your envelope domain. Under relaxed SPF (aspf=r), an envelope of bounce.example.com aligns to a From of example.com because they share an organizational domain, defined via the public suffix list in RFC 7489 section 3.1. Under aspf=s that same send fails SPF alignment, and only DKIM keeps DMARC alive.
  7. Map the failing source_ip values. If they resolve to a forwarder or a mailing list rather than your ESP, you have found the split: forwarding rewrites the envelope so SPF alignment breaks, which is the exact problem RFC 8617 (ARC) was written to work around.

Read the split as a table of causes

Once you have the parsed rows, the pattern of which recipients fail maps to a small set of causes. Match your symptom to the row below before changing anything.

What the RUA showsLikely causeWhich recipients failFix
auth_spf pass, eval_spf fail, DKIM alignedStrict SPF alignment (aspf=s) with a subdomain envelopeAll, unless DKIM carries themMove to aspf=r, or align the envelope domain to the From domain
Pass from your ESP IPs, fail from unrelated IPsForwarding or mailing list rewriting the envelopeRecipients on forwarders and lists onlyRely on aligned DKIM; ask intermediaries to ARC-seal
Fail only in a narrow time window, then recoversDNS TTL and caching after a record changeProviders still holding the old recordWait out the TTL; lower TTL before future edits
dkim_d is your ESP domain, not your From domainDKIM signed with the platform domain, not alignedEveryone, whenever SPF also does not alignConfigure a branded DKIM d= on your sending domain
Fail only from one provider, pass elsewherePer-provider enforcement or evaluation differenceOne mailbox provider's recipientsConfirm the provider honors policy; see the provider table

Why providers disagree on the same message

Two receivers can evaluate one identical message and reach opposite DMARC verdicts, because enforcement and forwarding handling are not uniform. Gmail requires at least one of SPF or DKIM to both authenticate and align, and treats relaxed alignment as sufficient in most cases. Microsoft 365 honors a published p=quarantine or p=reject policy by default when the recipient domain's MX points to Exchange Online, per Microsoft's DMARC configuration reference. A forwarder in front of either one can break SPF alignment entirely.

Receiver behaviorGmailMicrosoft 365 (EOP)A forwarder or list
Passes on one aligned identifierYesYesDepends on what survives the hop
Honors published enforcement policyYesYes, when MX points to itNot the enforcer; passes the message on
Effect on SPF alignmentPreserved for direct mailPreserved for direct mailBroken, envelope is rewritten
Effect on DKIM alignmentPreservedPreservedSurvives if the body is unchanged
Reads prior-hop results via ARCYesYes, for trusted ARC sealersAdds the ARC seal

Troubleshooting

  • Every report says pass, but a user swears it failed. Aggregate reports summarize streams, not individual messages, and a forwarded copy may never appear in your RUA. Ask the user for the message headers and read the DMARC line directly.
  • A major provider is missing from your reports. Not every receiver sends RUA, and some batch slowly. Absence is not a pass; widen the window to two weeks before concluding.
  • You just changed the record and results are split. That is TTL, not a bug. Confirm by checking whether the failing providers are reporting the old policy string, then wait for the TTL to expire.
  • DKIM shows pass but DMARC still fails. Read dkim_d. If it is your platform's shared domain rather than a subdomain of your From domain, the signature is valid but not aligned. Set up a branded signing domain. If you are also standing up a new subdomain to send from, sequence it against the reputation work in warming a new sending domain.

How to verify it worked

Do not trust a single test send. Confirm the fix two ways. First, in the next RUA cycle, the policy_evaluated pass rate for the affected header_from should approach 100 percent of your legitimate volume across every source_ip that belongs to you, with the earlier fail rows gone. Second, send one message to a Gmail account, open Show original, and confirm the header reads DMARC: PASS alongside SPF: PASS and DKIM: PASS. If you run multiple brands or sending domains, hold the aligned envelope and branded DKIM as a standing rule; the tradeoffs are covered in sending domain models for multi-brand senders.

Sources

M
Miloš Mitrović
Email Marketing for Ecommerce

Have a question or a project?

Whether it is about this post or a system you want built, I'm happy to talk.

Get in touch

404

Post not found. It may have been moved or the link is incorrect.

← Back to the blog
Summarize with AI
ChatGPT, Perplexity, and Grok open with the prompt ready to run. Claude, Gemini, and Copilot open a chat with the prompt copied; press Ctrl+V (Cmd+V on Mac) to paste. The full text is included, so it works even without web access.