You configured SPF (v=spf1 include:_spf.google.com ~all), generated a 2048-bit DKIM keypair, added the public key to your DNS records, and verified that dig TXT google._domainkey.yourdomain.com resolves cleanly. When you send a test email, the raw headers confirm spf=pass and dkim=pass.
Yet, your transactional emails still land in spam, or your newly configured DMARC aggregate reports (rua=mailto:...) show hundreds of messages marked with disposition: quarantine or disposition: reject.
The culprit is almost always a misunderstanding of DMARC alignment (RFC 7489). Passing SPF and passing DKIM are not enough—they must also align with the visible From: header in the user's email client.
Here are five subtle DMARC alignment traps that break email deliverability in production, and how to debug them.
1. Envelope-From vs. Header-From Mismatch (SPF Alignment Failure)
Email protocols maintain two different sender identities:
-
RFC 5321 Envelope-From (also known as
Return-Path,MAIL FROM, or bounce address): The address used by mail servers to route delivery status notifications and bounces. -
RFC 5322 Header-From (the visible
From:field): The address displayed to the recipient in their email client.
When you send emails through third-party services like AWS SES, SendGrid, or Mailgun, the SMTP envelope Return-Path defaults to their infrastructure domain (for example, 0100018...@amazonses.com or bounces.sendgrid.net).
SPF authenticates the sending server's IP against the domain found in the Return-Path. When SES sends the email, SPF passes because SES's IP is authorized for amazonses.com.
However, DMARC evaluates SPF alignment by checking whether the domain in Return-Path matches the domain in the From: header (yourdomain.com). Because amazonses.com does not match yourdomain.com, DMARC marks SPF as unaligned (fail).
The Fix: Configure a custom MAIL FROM / Return-Path domain in your provider's dashboard (e.g., mail.yourdomain.com or bounces.yourdomain.com) and add the corresponding CNAME/MX/SPF DNS records so the envelope domain matches your organization's domain.
2. Strict vs. Relaxed Alignment (aspf and adkim)
By default, DMARC operates in relaxed mode (aspf=r and adkim=r). In relaxed mode, subdomains are permitted to align with the organizational root domain:
- Header-From:
marketing@newsletter.example.com - DKIM domain (
d=tag):example.com -
Relaxed Alignment Result:
PASS(both share the rootexample.com)
If your DMARC record explicitly sets strict alignment (aspf=s or adkim=s), subdomains must match character-for-character. Under strict mode, the example above will fail DKIM alignment because newsletter.example.com != example.com.
The Fix: Keep aspf=r and adkim=r unless you have an explicit regulatory requirement for strict alignment. If you do use strict mode, ensure your signing keys use selectors and d= domains that match the exact subdomain of the sender.
3. Forwarding Breaks SPF (DKIM Survivability is Mandatory)
When a recipient forwards an email (or receives it through an automated distribution list or alias), the forwarding mail server retransmits the message from its own IP address.
The destination mail server evaluates SPF against the forwarder's IP address. Since the forwarder's IP is not in your domain's SPF record, SPF authentication fails 100% of the time on forwarded mail.
For forwarded email to pass DMARC, it must rely entirely on DKIM. However, many forwarding servers modify the message body (e.g., appending disclaimer footers or rewriting links), which invalidates the DKIM cryptographic body hash (bh=). When both SPF and DKIM fail alignment, DMARC triggers the policy action (quarantine or reject).
The Fix:
- Use DKIM canonicalization
c=relaxed/relaxedin your email generator so minor whitespace modifications during transit do not break cryptographic signatures. - Never rely on SPF alone for DMARC compliance; DKIM is the only protocol that survives multi-hop forwarding.
4. Subdomain Policy Inheritance (p= vs sp=)
When you publish a DMARC policy on your root domain:
v=DMARC1; p=reject; rua=mailto:dmarc@example.com
That p=reject policy automatically cascades down to every subdomain (such as staging.example.com, billing.example.com, or api.example.com) unless that subdomain explicitly defines its own DMARC record.
If an internal microservice or staging environment sends automated alert emails from alerts@staging.example.com without dedicated DKIM keys configured, recipient servers applying your root p=reject policy will silently drop the messages.
The Fix: When migrating to enforcement, use the sp= (subdomain policy) tag to maintain a lenient policy on subdomains until all services are verified:
v=DMARC1; p=quarantine; sp=none; rua=mailto:dmarc@example.com
5. Decoding Raw RUA Aggregate XML Reports
When you configure rua=mailto:..., receiving mailbox providers (Google, Microsoft, Yahoo) send automated daily aggregate reports in compressed .xml.gz or .zip format.
Inside the XML, you will see records structured like this:
<record>
<row>
<source_ip>198.51.100.42</source_ip>
<count>85</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>sendgrid.net</domain>
<result>pass</result>
</dkim>
<spf>
<domain>sendgrid.net</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
Notice the crucial distinction: <auth_results> shows dkim=pass and spf=pass for sendgrid.net, but <policy_evaluated> shows dkim=fail and spf=fail because neither authenticated domain matched the <header_from> domain example.com.
If you receive these raw XML reports and want to inspect them without uploading sensitive email metadata to a third-party service, you can use the Nutilz DMARC Analyzer. It parses RUA XML reports client-side in your browser, mapping sending IPs, alignment statuses, and disposition verdicts into an interactive breakdown.
Production Checklist for 100% DMARC Alignment
To achieve clean deliverability across major email providers:
- Audit Sending Sources: Identify all systems sending on behalf of your domain (transactional mailers, CRM, helpdesk, CI/CD alerts).
-
Configure Custom Return-Path: Set up custom bounce domains (
bounces.yourdomain.com) in your email providers so SPF aligns with yourFrom:domain. -
Sign with 2048-bit DKIM: Use
c=relaxed/relaxedcanonicalization and ensure thed=tag matches your root domain or exact sending subdomain. -
Monitor Before Enforcing: Start at
p=none, analyze incoming aggregate reports using Nutilz DMARC Analyzer, and verify alignment before stepping up top=quarantineandp=reject.
Top comments (0)