SPF passes, DMARC fails: the alignment trap
You added your ESP. SPF is green. DKIM is green. Then you glance at your DMARC aggregate reports and see authentication failures for a chunk of mail you know is legitimate. The frustrating part: the individual SPF and DKIM checks are passing for those exact messages.
This is the alignment problem. It’s one of the most common misunderstandings in DMARC deployment, and it costs teams days of debugging because the failure mode makes no intuitive sense at first.
SPF passing ≠ DMARC passing
DMARC doesn’t just ask “did SPF pass?” It asks “did SPF pass for the right domain?”
Specifically, DMARC requires that the domain used in SPF authentication aligns with the domain in the From: header of the message. This is called SPF alignment, and it’s defined in RFC 9989 §4.4.2 (“SPF-Authenticated Identifiers”).
When you send email through SendGrid, Amazon SES, Mailgun, or any similar service, the actual SMTP envelope, the technical metadata the sending server uses, contains a different domain than what your recipients see in the From: header.
That envelope field is the MAIL FROM identity (also called “envelope from” or “Return-Path”). It identifies where bounces should go. When SendGrid handles your email, the envelope from looks something like:
bounces+user-123@em4567.yourdomain.sendgrid.net
SPF evaluates the envelope from domain. If em4567.yourdomain.sendgrid.net is in your SPF record, SPF passes. But your From: header says you@example.com. DMARC looks at both and asks: do these domains match?
They don’t. DMARC fails, despite SPF passing.
Why services work this way
Bounce handling is the reason. When an email bounces, bad address, full mailbox, server rejection, the bounce notification goes back to the envelope from address. If your ESP used your actual domain as the envelope from, they’d have no way to route bounce notifications to your account. Every ESP in the world uses their own infrastructure domain for the envelope from. That’s not a misconfiguration; it’s how the plumbing works.
The consequence: SPF authentication alone is structurally insufficient for DMARC if you use external sending services. This isn’t a quirk of SendGrid or SES. It’s true for all of them.
DKIM solves this, if you set it up correctly
DKIM alignment works differently. DKIM signs the message content using a key associated with a domain, and that domain is carried in the signature itself, the d= tag defined in RFC 6376 §3.5. DMARC checks whether the d= domain in the DKIM signature aligns with the From: header domain (RFC 9989 §4.4.1, “DKIM-Authenticated Identifiers”).
When you configure a custom DKIM domain on your ESP, you’re telling them to sign messages with a key from your domain, not theirs. The DKIM signature then says d=example.com. That aligns with From: you@example.com. DMARC passes.
This is why custom DKIM setup is not optional if you want reliable DMARC pass rates. It’s the mechanism that produces the alignment DMARC needs.
Without custom DKIM, your ESP signs messages with their own domain (d=sendgrid.net or d=amazonses.com). That doesn’t align with your From: domain. You’re left dependent on SPF alignment, which, as explained above, is broken by design for third-party senders.
What relaxed and strict alignment mean
DMARC supports two alignment modes: relaxed (the default) and strict. You set this in your DMARC record with aspf= for SPF alignment and adkim= for DKIM alignment.
Under relaxed alignment, subdomains count. If your From: header says @example.com and the authenticating domain is mail.example.com, DMARC considers that aligned. The organizational domains must match. That’s the registered domain, found by walking up the DNS tree, not by dropping one label: for mail.example.co.uk it’s example.co.uk.
Under strict alignment, exact domain matching is required. mail.example.com does not align with example.com under strict mode.
Most deployments use relaxed alignment (the default, no explicit aspf= or adkim= tag needed). This covers the common case where your ESP signs with a subdomain of your domain. Strict mode is appropriate for high-security environments where you want to prevent subdomain spoofing, but it increases the risk of legitimate mail failing authentication if your configuration isn’t tight.
If you’re debugging alignment failures, check your DMARC record first. A record with adkim=s (strict DKIM) will reject signatures from mail.example.com even though they’re technically your subdomain.
How to diagnose alignment failures in your reports
DMARC aggregate reports (rua) show per-message authentication results. For each row, you’ll see:
- The source IP that sent the message
- The header
From:domain - SPF result and the domain SPF evaluated against (the envelope from domain)
- DKIM result and the
d=domain from the signature
An alignment failure looks like this in practice:
| From domain | SPF result | SPF domain | DKIM result | DKIM domain | DMARC |
|---|---|---|---|---|---|
| example.com | pass | em4567.yourdomain.sendgrid.net | none | n/a | fail |
SPF passed. DKIM didn’t run (or used the wrong domain). Neither mechanism produced alignment. DMARC fails.
The fix target is obvious from this view: get DKIM passing with d=example.com or a subdomain of it.
The checklist for fixing alignment
Step 1: identify which ESP or service is generating the failures.
Look at the source IP in the failing rows of your DMARC report. Match the IP to the service sending it. DMARC aggregate reports use IP addresses, not friendly names, but your ESP’s documentation lists their IP ranges and you can cross-reference. A sender-attribution tool can suggest which provider is behind a source IP so you don’t have to look up ranges by hand every time, but treat that as a lead to confirm against the ESP’s own documentation, not as proof on its own.
Step 2: configure custom DKIM for that service.
Every major ESP supports this. The process is roughly the same across providers:
- Go to your ESP’s account settings and find the domain authentication or DKIM section
- They generate a public/private key pair
- You publish the public key as a DNS TXT record using a CNAME or direct TXT record at a specific subdomain they specify
- You verify the record in their dashboard
- They start signing outbound messages with your domain
For SendGrid: Settings → Sender Authentication → Domain Authentication For Amazon SES: Configuration → Verified identities → your domain → DKIM signatures For Mailgun: Sending → Domains → your domain → DKIM For Postmark: Sender Signatures → your domain → DKIM
Step 3: confirm DKIM alignment after 24–48 hours.
Send a test message through the service after the DNS change propagates. Check the raw message headers, look for Authentication-Results: from your receiving server (RFC 8601). You should see dkim=pass with the d= tag showing your domain.
Then wait for your next DMARC aggregate report delivery (typically daily, from major receivers like Google and Yahoo). The rows from that sending IP should now show DKIM aligned passes and DMARC pass.
Step 4: handle services that don’t support custom DKIM.
Some older or simpler services don’t offer custom DKIM signing. In that case, SPF alignment is your only option, and you need the envelope from domain to align with your From: domain.
This is rare with major ESPs but common with legacy systems, some ticketing tools, and some CRM integrations. For those services, check whether they support custom bounce domains (Return-Path customization). If they allow you to set the envelope from to a subdomain of your own domain, SPF alignment will work under relaxed mode.
If the service supports neither custom DKIM nor custom Return-Path, you have a genuine problem: those messages cannot pass DMARC alignment. Your options are to replace the service, route the email differently, or accept that those messages will fail alignment and exclude that source from your DMARC enforcement policy.
Moving from p=none to p=reject safely
For a step-by-step rollout plan, see Moving DMARC from p=none to p=reject safely.
The alignment problem is exactly why experts recommend staying at p=none while you audit all your sending sources. Until you’ve confirmed that every service sending email on behalf of your domain has working alignment, either via DKIM or SPF, enforcing p=quarantine or p=reject will start silently killing legitimate mail.
The process:
- Deploy
p=nonewithrua=pointing to your reporting address - Collect reports for 2–4 weeks
- Map every sending IP to a service
- Fix alignment for each service (DKIM first, SPF alignment as fallback)
- Confirm clean passes in reports
- Move to
p=quarantineonce the failure rate is near zero - Move to
p=rejectafter a further verification period
Rushing this process is how teams break their own email delivery.
One more thing: forwarding breaks SPF alignment by design
Email forwarding introduces a specific alignment failure that isn’t fixable (covered in detail in Why forwarded email fails SPF, and why DKIM is the only thing saving you): when a server forwards a message, it rewrites the envelope from to itself but preserves the original From: header. SPF evaluation happens against the forwarding server’s IP and domain, which won’t match your SPF record. This causes SPF failures, and SPF alignment failures, for forwarded mail.
This is expected behavior. DKIM survives forwarding (the signature is over the message body and certain headers, which a forwarding server doesn’t change). If you see alignment failures from IP addresses associated with mail providers that are not your sending services, forwarding is the likely cause. These failures don’t indicate a security problem and don’t need to be “fixed.” They’re a normal artifact of how email forwarding works.
The practical implication: DKIM alignment survives more real-world changes than SPF alignment does. Get DKIM working on your sending services and your DMARC pass rate will be more stable.
DMARC Guardian’s reports group by sender and by source IP, with an “Issues only” filter so alignment failures don’t get buried under a wall of green passes. If you’re troubleshooting a service that’s passing SPF but failing DMARC, the DNS page and the sender attribution column are the right place to start.
Check who’s sending as your domain right now, free, no signup →