Skip to content
correct.email
Email authentication

DMARC alignment explained with real headers

Why SPF and DKIM can pass while DMARC fails: From vs Return-Path vs DKIM d=, relaxed and strict alignment, organizational domains and how to fix it.

By Exmoor Software5 min read

spf=pass, dkim=pass, dmarc=fail is the most confusing line you can find in an email header, and it almost always means the same thing: an alignment problem. DMARC doesn’t ask whether SPF or DKIM passed. It asks whether they passed for the domain in the From address.

This guide shows which domains a message carries, how RFC 9989 compares them, and how to read and fix real headers.

Three domains in every message

IdentityWhere you see itChecked byExample
From domain (RFC 9989: Author Domain)From: headerDMARC — this is what it protectsexample.com
Envelope sender (MAIL FROM)Return-Path: header; smtp.mailfrom= in Authentication-ResultsSPFbounces.mailer.example.net
DKIM signing domaind= in DKIM-Signature; header.d= in Authentication-ResultsDKIMmailer.example.net

A message passes DMARC when at least one of these is true:

  • SPF passes, and the envelope sender domain is aligned with the From domain;
  • a DKIM signature verifies, and its d= domain is aligned with the From domain.

A message can carry several DKIM signatures; one verified, aligned signature is enough. For SPF, DMARC uses only the result for the MAIL FROM identity, not the separate HELO check.

Relaxed and strict alignment

Your DMARC record sets the mode separately for DKIM (adkim) and SPF (aspf). Both default to r, relaxed:

  • Relaxed — the two domains have the same organizational domain.
  • Strict (s) — the two domains are identical.
Authenticated domainFrom domainRelaxedStrict
example.comexample.comalignedaligned
bounce.example.comexample.comalignednot aligned
example.comnews.example.comalignednot aligned
mailer.example.netexample.comnot alignednot aligned

Comparisons ignore letter case. RFC 9989 notes that nearly all domain owners find relaxed alignment sufficient. A record that tightens only DKIM looks like this:

_dmarc.example.com.  3600  IN  TXT  "v=DMARC1; p=reject; adkim=s; rua=mailto:dmarc-reports@example.com"

Organizational domains and the DNS Tree Walk

Relaxed alignment needs to know the organizational domain of each name. RFC 7489 took it from the Public Suffix List. RFC 9989 replaces that with the DNS Tree Walk: the receiver queries _dmarc records from the domain upwards, with at most eight queries, and among the names where it found a valid DMARC record it picks the one with the fewest labels. Two tags change the outcome:

  • psd=n — this domain is an organizational domain for itself and everything below it;
  • psd=y — this is a public suffix, published by its operator (for example a registry); the organizational domain is one label below it.

If no record is found at all, the domain is its own organizational domain — and if the From domain has no applicable DMARC record, DMARC doesn’t apply to the message.

An example: mail with From: news.example.com and Return-Path in bounce.example.com, with a DMARC record only at _dmarc.example.com:

_dmarc.news.example.com    → no record
_dmarc.example.com         → "v=DMARC1; p=reject; …"
_dmarc.com                 → no record

Both names lead to example.com, so SPF is aligned in relaxed mode. Now suppose a department publishes "v=DMARC1; p=reject; psd=n" at _dmarc.dept.example.com. From then on, dept.example.com is its own organizational domain, and mail from it signed with d=example.com is not aligned, not even in relaxed mode.

For ordinary domains both methods give the same answer. The difference shows up in multi-level structures and with psd tags.

Worked examples

SPF and DKIM pass, DMARC fails

A newsletter sent through an email service before domain authentication was set up:

Return-Path: <bounce-7f3a@bounces.mailer.example.net>
Authentication-Results: mx.example.org;
       spf=pass smtp.mailfrom=bounces.mailer.example.net;
       dkim=pass header.d=mailer.example.net header.s=m1;
       dmarc=fail header.from=example.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailer.example.net; s=m1; …
From: Example Shop <news@example.com>

SPF passed for bounces.mailer.example.net, DKIM for mailer.example.net. Neither shares an organizational domain with example.com, so nothing is aligned and DMARC fails. Under p=reject, this legitimate newsletter would be rejected.

Custom return-path: SPF aligned

The same service after you set up a bounce domain under your own domain:

Return-Path: <bounce-7f3a@bounce.example.com>
Authentication-Results: mx.example.org;
       spf=pass smtp.mailfrom=bounce.example.com;
       dkim=pass header.d=mailer.example.net header.s=m1;
       dmarc=pass header.from=example.com
From: Example Shop <news@example.com>

bounce.example.com and example.com share the organizational domain, so SPF is aligned in relaxed mode and DMARC passes. With aspf=s it would fail. DMARC now rests on SPF alone, which breaks as soon as the message is forwarded.

Custom DKIM: DKIM aligned

The service now signs with your domain:

Authentication-Results: mx.example.org;
       spf=pass smtp.mailfrom=bounces.mailer.example.net;
       dkim=pass header.d=example.com header.s=esp1;
       dmarc=pass header.from=example.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=esp1; …
From: Example Shop <news@example.com>

d=example.com is identical to the From domain, so DKIM is aligned even in strict mode. This is the fix to make first, because the signature travels with the message.

Forwarded message

Your message forwarded from a university address to a private mailbox:

Authentication-Results: mx.example.org;
       spf=fail smtp.mailfrom=example.com;
       dkim=pass header.d=example.com header.s=s2026;
       dmarc=pass header.from=example.com

The forwarding server isn’t in your SPF record, so SPF fails. If the forwarder rewrites the envelope sender, SPF passes for its domain instead — still not aligned. The DKIM signature survived, so DMARC passes. A mailing list that edits the subject or adds a footer breaks DKIM as well, and then DMARC fails.

Strict DKIM and a subdomain in From

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; adkim=s"

Authentication-Results: mx.example.org;
       spf=pass smtp.mailfrom=mailer.example.net;
       dkim=pass header.d=example.com header.s=s2026;
       dmarc=fail header.from=news.example.com

news.example.com has no record of its own, so the record at example.com applies, including adkim=s. d=example.com is not identical to news.example.com, so DKIM isn’t aligned. Either sign with d=news.example.com or go back to relaxed DKIM alignment.

How to fix misalignment

  1. Custom DKIM domain at each provider. Providers call it domain authentication, custom DKIM or sender authentication: you publish the records they give you (often CNAMEs under _domainkey) and they sign with d= set to your domain. Do this first.
  2. Custom return-path. Also called custom MAIL FROM or bounce domain: a subdomain such as bounce.example.com that points to the provider, so SPF passes for a domain within your organizational domain. It aligns only in relaxed mode.
  3. Your own servers. Sign with your domain and use an envelope sender in your domain that your SPF record covers.

What doesn’t help: adding the provider’s include: to your SPF record while it still uses its own envelope sender, accepting a DKIM signature for the provider’s domain, or changing Reply-To, which DMARC doesn’t look at.

Check alignment yourself

  1. Send a message to a mailbox at a large provider, open the original and paste the headers into the email header analyzer. It shows smtp.mailfrom, header.d and the From domain side by side. Its alignment estimate uses the Public Suffix List, so in rare multi-level setups an RFC 9989 receiver may decide differently. How to read email headers explains the rest of the header block.
  2. Run the DMARC checker to see which record applies to your From domain and its adkim and aspf settings.
  3. Read your aggregate reports: for every source, compare the raw auth_results with the aligned policy_evaluated results — see How to read DMARC aggregate reports.

For the bigger picture of how SPF, DKIM and DMARC fit together, see SPF vs DKIM vs DMARC.

References