One of the most confusing moments in email troubleshooting happens when you inspect an email's raw headers (or a DMARC aggregate report) and see:
spf=passdkim=passdmarc=fail
How can DMARC fail when both SPF and DKIM passed?
The answer is Identifier Alignment. Raw SPF and DKIM checks only verify whether the domain they tested is authentic. DMARC adds a stricter requirement: the domain authenticated by SPF or DKIM must match the visible From: header domain that the human recipient actually sees in their email client.
If you want to verify your domain's current records before diving into header diagnostics, run a quick check with the MailPosture Domain Scanner.
The 3 domains inside every email (and why they don't always match)
Every email message carries three distinct domain identifiers that play a role in authentication:
| Identifier | Technical Name | Where It Lives | Who Sees It | Checked By |
|---|---|---|---|---|
| Header From | RFC5322.From | From: Billing <billing@acme.com> | The recipient in Gmail/Outlook | DMARC (the target domain that must align) |
| Envelope From / Return-Path | RFC5321.MailFrom | Return-Path: <bounce@esp-mailer.net> | Hidden in raw headers (receives bounces) | SPF |
| DKIM Signing Domain | d= tag in DKIM-Signature | DKIM-Signature: v=1; ... d=acme.com; s=s1; | Hidden in raw headers | DKIM |
For DMARC to pass, at least one of the following must be true:
- SPF passes AND the
Return-Pathdomain aligns with theHeader Fromdomain (SPF Alignment), OR - DKIM passes AND the
DKIM-Signatured=domain aligns with theHeader Fromdomain (DKIM Alignment).
Notice that you only need one of the two (SPF or DKIM) to pass with alignment for DMARC to evaluate to dmarc=pass. However, configuring both gives you resilience when messages are forwarded.
Real-world Example: Why spf=pass + dkim=pass still causes dmarc=fail
Suppose your company acme.com uses a third-party invoicing platform (cloudbilling-mail.io) to email customer receipts. You even added include:spf.cloudbilling-mail.io to acme.com's SPF record.
When a customer views "Show Original" in Gmail, here is what the headers look like:
Authentication-Results: mx.google.com;
dkim=pass header.i=@cloudbilling-mail.io header.s=sc1;
spf=pass (google.com: domain of bounce-8821@cloudbilling-mail.io designates 198.51.100.42 as permitted sender) smtp.mailfrom=bounce-8821@cloudbilling-mail.io;
dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=QUARANTINE) header.from=acme.com
Return-Path: <bounce-8821@cloudbilling-mail.io>
From: "Acme Billing" <billing@acme.com>
Look closely at the three domains in that header block:
- Visible
From:(header.from):acme.com - SPF
Return-Path(smtp.mailfrom):cloudbilling-mail.io— SPF passed againstcloudbilling-mail.io, notacme.com! Addinginclude:spf.cloudbilling-mail.iotoacme.com's SPF record accomplished nothing because the receiving server never queriedacme.comfor SPF; it queried theReturn-Pathdomain (cloudbilling-mail.io). - DKIM signing domain (
header.i/d=):cloudbilling-mail.io— The vendor signed the message with their own shared DKIM key instead of your customacme.comkey.
Because neither cloudbilling-mail.io (SPF) nor cloudbilling-mail.io (DKIM) matches acme.com (header.from), both SPF alignment and DKIM alignment fail, resulting in dmarc=fail.
Relaxed (r) vs Strict (s) alignment explained
DMARC supports two alignment modes for SPF (aspf=) and DKIM (adkim=):
| Alignment Mode | DMARC Tag | Rule | If Header From is acme.com, Which Domains Align? |
|---|---|---|---|
| Relaxed (Default) | adkim=r; aspf=r | Organizational root domain must match. Subdomains are allowed. | acme.com, mail.acme.com, em1.billing.acme.com |
| Strict | adkim=s; aspf=s | Exact fully qualified domain name (FQDN) must match character-for-character. | Only acme.com (mail.acme.com fails strict alignment!) |
Trap: Accidental failure from aspf=s (Strict SPF alignment)
Almost every modern ESP (SendGrid, Postmark, Mailgun, Amazon SES, HubSpot, Customer.io) implements custom SPF Return-Path alignment by asking you to create a CNAME or MX/TXT record on a subdomain such as em1234.acme.com or bounces.acme.com, while your visible From: address is hello@acme.com.
- Under relaxed SPF alignment (
aspf=r),em1234.acme.comandacme.comshare the organizational domainacme.com, so SPF alignment passes. - If someone sets
aspf=sin your_dmarc.acme.comrecord thinking "strict is more secure,"em1234.acme.comno longer matchesacme.comexactly, immediately breaking SPF alignment across all of your ESPs.
How to fix SPF alignment vs DKIM alignment
Fixing DKIM Alignment (Highest Priority)
DKIM alignment is the gold standard because the DKIM-Signature header travels with the message even if the recipient has an auto-forwarder (e.g., forwarding an alumni or custom domain address to a personal Gmail account).
- Open your email provider or SaaS tool's Domain Authentication / Custom DKIM settings.
- Generate custom DKIM records for
yourdomain.com(either 1–2 TXT records atselector._domainkey.yourdomain.comor 2–3 CNAME records delegatings1._domainkey.yourdomain.comto the vendor). - Publish the records in DNS and verify them with the Free DKIM Checker.
- Send a test email and verify that
Authentication-Resultsshowsdkim=pass header.i=@yourdomain.com.
Fixing SPF Alignment (Custom Return-Path / Bounce Domain)
- In your ESP's settings, look for Custom Return-Path, Custom Bounce Domain, or Link/Domain Branding.
- Create the CNAME record the ESP provides (for example,
bounces.yourdomain.compointing tobounces.esp-provider.com). - Because the Return-Path is now
bounces.yourdomain.com, the receiving server queries the SPF record onbounces.yourdomain.com(which the ESP manages via the CNAME). - This achieves two wins at once:
bounces.yourdomain.comaligns withFrom: user@yourdomain.comunderaspf=r, AND it costs zero lookups on your root domain's 10-lookup SPF budget!
Troubleshooting Checklist: Why is my aligned sender still failing?
If you configured custom DKIM and Return-Path alignment in your ESP but still see failures in your DMARC aggregate reports, check these four culprits:
- You added the domain in the ESP console, but a specific campaign or API key is still using the default shared sender. Many transactional APIs require passing the authenticated domain or re-verifying the sender identity after DNS verification completes.
- Email forwarding broke SPF, and DKIM was invalidated in transit. Mailing lists (like Google Groups or Mailman) often modify the
Subject:line (e.g., adding[Team-List]) or append a footer to the message body. Modifying the body invalidates the cryptographic DKIM hash unless the sender and forwarder support ARC (Authenticated Received Chain). - CNAME flattening at your DNS provider broke DKIM CNAME delegation. If you use Cloudflare, ensure the orange cloud (HTTP proxy) is turned OFF (DNS Only / grey cloud) for all
_domainkey,_dmarc, and custom Return-Path CNAME records. - Your root SPF record is returning
PermError. If you use the root domain itself as the Return-Path (such as Google Workspace or Microsoft 365 direct mail) and your root SPF record has more than 10 DNS lookups, SPF returnspermerrorand cannot align.
Validate your alignment in seconds
Use the Free SPF Checker, Free DKIM Checker, and Free DMARC Checker to verify each layer individually, or run a unified MailPosture Domain Scan to inspect your complete authentication posture.