DMARC for Transactional Email: SendGrid, Mailgun, Amazon SES, Postmark, SparkPost, Mailjet, Resend, MailerSend, Brevo — Custom-Domain DKIM, Return-Path Alignment, and ESP Selector Conventions
The deployment guide for DMARC on transactional email sent through third-party ESPs (SendGrid, Mailgun, Amazon SES, Postmark, SparkPost, Mailjet, Resend, MailerSend, Brevo): why SPF alignment is unreliable for ESPs, the CNAME-delegated custom-domain DKIM path as the load-bearing alignment mechanism, per-ESP selector conventions, Return-Path configuration for secondary SPF alignment, dedicated-subdomain segmentation, multi-ESP authentication strategies, dedicated vs shared IP implications, and the Feb 2024 Google / Yahoo bulk-sender requirements anchor.
This deployment guide is provided in English. ESP / DMARC / DKIM operational vocabulary (Easy DKIM, custom-domain DKIM, CNAME delegation, Return-Path, envelope MAIL FROM, header From, sender signature, configuration set, dedicated IP, shared IP, IP warmup, bounce domain) and the per-ESP selector / hostname identifiers (s1._domainkey, s2._domainkey, mailo._domainkey, mta._domainkey, scph0316._domainkey, mailjet._domainkey, resend._domainkey, mlsend._domainkey, mlsend2._domainkey, amazonses.com, sendgrid.net, mailgun.org) are vendor-canonical terms that do not translate. We keep the body in the source language so the configuration values remain copy-paste safe across locales.
TL;DR
- DKIM is the load-bearing alignment
mechanism for transactional email, not
SPF. Most ESPs (SendGrid, Mailgun, Amazon SES,
SparkPost) rewrite the envelope MAIL FROM to a
bounce-handling domain under their control, so
SPF aligns with that domain rather than with
your visible
From:header. DKIM with a custom-domain selector is what makes DMARC pass. - Every ESP has its own DKIM selector
convention. SendGrid uses
s1._domainkey+s2._domainkey(rotating pair); Mailgun usesmailo._domainkey(newer) ormta._domainkey(legacy); Amazon SES Easy DKIM uses three random<token>._domainkeyCNAMEs; Postmark uses a date-named selector TXT record; SparkPost usesscph0316._domainkey; Mailjet usesmailjet._domainkey; Resend usesresend._domainkey. - Publish all CNAMEs as the ESP
instructs, then verify with
dig. A typical verification command isdig +short cname s1._domainkey.your-domain.comfor SendGrid ordig +short txt mailo._domainkey.your-domain.comfor Mailgun. - Use a dedicated subdomain for
transactional mail -
transactional.example.com,mail.example.com, ormg.example.comisolates reputation from corporate mail (Workspace / M365) and marketing mail. Independent DMARC policy via thenp=/sp=tags lets the apex rampp=rejectwhile a subdomain remains atp=noneduring ESP onboarding. - Configure a custom Return-Path /
bounce subdomain
(
em.your-domain.com,bounces.your-domain.com, ormailo.your-domain.com) as a CNAME to the ESP's bounce hostname to enable SPF alignment as a SECONDARY path - DKIM remains primary. SendGrid, Mailgun, and Amazon SES all support this; Postmark handles bounces internally so the custom Return-Path step is not applicable. - The Feb 2024 Google / Yahoo
bulk-sender requirements mandate
DMARC at
p=quarantineor stricter for senders above 5000 messages/day. Transactional senders routinely exceed this threshold; deferred deliverability or bulk foldering at scale is the consequence of missing DMARC alignment. - Watch the SPF 10-DNS-lookup
limit (RFC 7208 section 4.6.4) when
adding multiple ESP includes to the apex SPF
record.
include:sendgrid.net+include:mailgun.org+include:amazonses.com+include:_spf.google.comalready consumes 4-6 lookups before counting redirects. Dedicated subdomains per ESP keep each SPF record under the limit. - The DMARC Analyzer dashboard
surfaces per-source-IP alignment per ESP
via
source_ip_detail.php+reporter_detail.php. Use it to verify each ESP's outbound IP range is producing aligned messages before advancing the DMARC policy.
1. What this guide covers
This guide is the operator walkthrough for deploying SPF, DKIM, and DMARC on a domain whose transactional email is sent by a third-party Email Service Provider (ESP). The page covers the ten most-deployed ESPs in 2026:
- Twilio SendGrid - the largest
transactional-email platform by volume.
Authenticated Domain CNAMEs at
em.<your-domain>,s1._domainkey.<your-domain>,s2._domainkey.<your-domain>. - Mailgun (Sinch) - the
developer-focused API platform with regional
EU / US infrastructure. DKIM CNAME at
mailo._domainkey.<your-domain>(newer accounts) ormta._domainkey/pic._domainkey(legacy). - Amazon SES (Simple Email
Service) - the AWS transactional-email
platform. Easy DKIM generates three random
<token>._domainkeyCNAMEs pointing to<token>.dkim.amazonses.com. Optional custom MAIL FROM atmail.<your-domain>. - Postmark (ActiveCampaign) -
transactional-only, optimized for fast
delivery and high inbox placement. DKIM
published as a TXT record (NOT a CNAME) at
<selector>._domainkey.<your-domain>where the selector is the literal date or the Sender Signature name. - SparkPost (MessageBird) - the
enterprise transactional platform with
bring-your-own-infrastructure deployment.
DKIM CNAME at
scph0316._domainkey.<your-domain>. - Mailjet (Sinch) - the
European transactional-email platform with
EU-residency guarantees. DKIM CNAME at
mailjet._domainkey.<your-domain>. - Sendinblue / Brevo - the
European all-in-one (transactional +
marketing) platform. DKIM CNAME at
mail._domainkey.<your-domain>and a TXT record atbrevo-code:<hash>for domain verification. - Resend - the developer-API
platform built by the React Email team. DKIM
CNAME at
resend._domainkey.<your-domain>. - MailerSend - the
transactional-and-marketing platform with
Inbound Routing support. DKIM CNAMEs at
mlsend._domainkey.<your-domain>andmlsend2._domainkey.<your-domain>. - Mandrill (Mailchimp
transactional) - the transactional add-on to
the Mailchimp marketing platform. DKIM uses
the Mailchimp domain authentication CNAMEs at
k1._domainkey.<your-domain>andk2._domainkey.<your-domain>.
Beyond these ten the same universal pattern applies to Pepipost / Netcore, Elastic Email, SocketLabs, SMTP2GO, Mailtrap, SES Lite, and any other ESP that supports custom-domain authentication: a DKIM CNAME (or TXT) at an ESP-specified selector pointing to the ESP's key infrastructure, optional Return-Path / bounce subdomain CNAME, and an SPF include at the apex.
Companion pages: the four mailbox-provider deployment guides (DMARC for Google Workspace, DMARC for Microsoft 365, DMARC for cPanel & Shared Hosting, DMARC for Plesk, DirectAdmin, ISPConfig) cover the OUTBOUND MTA you control. This page covers the OUTBOUND MTA an ESP runs for you.
2. Why transactional email needs different DMARC handling
Transactional email differs from mailbox-provider outbound mail in three ways that fundamentally change the DMARC deployment surface.
2.1 Envelope MAIL FROM rewriting (the SPF alignment break)
When you send mail through Google Workspace,
Microsoft 365, or your own Postfix / Exim MTA,
the envelope MAIL FROM
(RFC 5321 section 4.1.1.2) and the visible header
From: (RFC 5322 section 3.6.2) are
typically the same domain - your-domain.com sends
on behalf of your-domain.com, and SPF aligns
natively. When you send mail through an ESP, the
ESP rewrites the envelope MAIL FROM
to a domain it controls (typically
bounces.sendgrid.net,
bounce.mailgun.org, or
<region>.amazonses.com) so the
ESP can handle delivery failures via its own
bounce-processing infrastructure. SPF
authentication passes for the ESP's bounce domain
against the ESP's published SPF record - but
DMARC's identifier alignment
requirement compares the SPF-authenticated domain
against the header From: domain, and
the two no longer match.
Result: the message passes SPF authentication but fails SPF alignment, which fails DMARC unless DKIM alignment succeeds independently.
2.2 Shared signing infrastructure (the DKIM custom-domain requirement)
By default an ESP signs every outbound message
with its own signing domain
(d=sendgrid.net,
d=mailgun.org,
d=amazonses.com). This satisfies the
ESP's deliverability but does NOT align with your
header From: domain - the receiver
sees a DKIM signature valid for the ESP, but
DMARC requires the DKIM d= to match
(in relaxed alignment) or exactly equal (in
strict alignment) your-domain.com.
The fix is custom-domain DKIM:
you publish a CNAME at the ESP-specified
selector under your-domain.com pointing to the
ESP's key infrastructure. The ESP signs your
outbound messages with
d=your-domain.com s=<esp-selector>,
the receiver follows the CNAME to fetch the
public key from the ESP, and DKIM aligns with
the header From:. The private key
never leaves the ESP - the CNAME delegation is
purely a public-key-lookup redirection.
2.3 Feb 2024 Google / Yahoo bulk-sender requirements
Effective February 2024, Google and Yahoo
require senders above 5000 messages/day to
Gmail / Yahoo Mail to publish DMARC at
p=quarantine or stricter, maintain
SPF + DKIM alignment, configure one-click
unsubscribe per RFC 8058, keep complaint rates
below 0.1 percent, and use a custom Return-Path /
bounce domain. Transactional senders routinely
exceed 5000 messages/day in production
deployments. Failing the bulk-sender requirements
results in:
- Deferred delivery (4xx temp-fail) at receiver scale, raising your apparent latency to end users.
- Bulk-folder routing for messages that pass the spam filter but fail the bulk-sender checks - users never see the password reset because Gmail filed it under Promotions.
- Outright reject (5xx perm-fail) when the Feb 2024 requirements are missed badly enough - typically only when DMARC is at p=none AND SPF / DKIM are both unaligned.
DMARC alignment for transactional email is no longer a security-only concern; it is a deliverability requirement at scale.
3. The SPF alignment trap
The most common DMARC failure mode for
transactional email is SPF passes but
DMARC fails. Operators see SPF=pass in
the Authentication-Results header,
assume DMARC will follow, and are surprised when
aggregate reports show DMARC=fail. The trap is
the difference between SPF AUTHENTICATION and SPF
ALIGNMENT.
3.1 SPF authentication vs SPF alignment
SPF authentication (RFC 7208)
asks: does the connecting client IP appear in the
SPF record published at the envelope
MAIL FROM domain? For an ESP-routed
message the envelope domain is the ESP's bounce
domain (e.g.
bounces.sendgrid.net), the connecting
IP is an ESP outbound IP, and the SPF record
published at the ESP's bounce domain includes
that IP. SPF authentication passes.
SPF alignment (RFC 7489 section
3.1.1) asks: does the SPF-authenticated domain
match the header From: domain? For
the same message the SPF-authenticated domain is
bounces.sendgrid.net and the header
From: is
your-domain.com. The two domains do
not share an organizational domain, so SPF
alignment fails - even in DMARC's relaxed
alignment mode (aspf=r), which only
requires sharing the organizational domain after
Public Suffix List trimming.
Result: SPF=pass + SPF-not-aligned + (DKIM=pass or DKIM=fail) -> DMARC=pass only if DKIM aligns, otherwise DMARC=fail.
3.2 Reading the trap in aggregate reports
In an RFC 7489 aggregate (RUA) report the trap
surfaces as a record with
policy_evaluated.dmarc=fail but
auth_results.spf.result=pass AND
auth_results.spf.domain set to the
ESP's bounce domain
(bounces.sendgrid.net,
bounce.mailgun.org,
amazonses.com) rather than your
header From: domain. The
DMARC Analyzer dashboard surfaces this via the
source IP detail
view, which shows the SPF-authenticated
domain alongside the alignment verdict for every
source IP. The fix is either configure
custom-domain DKIM (primary) or configure a
custom Return-Path / bounce subdomain (secondary,
enables SPF alignment).
3.3 Custom Return-Path closes the SPF gap
Some ESPs (SendGrid, Mailgun, Amazon SES) let
you configure a custom Return-Path /
bounce subdomain: you publish a CNAME
at em.your-domain.com (SendGrid),
mailo.your-domain.com (Mailgun), or
mail.your-domain.com (Amazon SES
custom MAIL FROM) pointing to the ESP's bounce
infrastructure. The ESP then sets the envelope
MAIL FROM to your custom bounce
subdomain instead of its own, so the
SPF-authenticated domain becomes a subdomain of
your organizational domain and SPF alignment
passes natively. The SPF record at the bounce
subdomain typically includes the ESP via
include: mechanism. Section 6 below
documents the per-ESP setup; section 4
documents the DKIM path which is the primary fix.
4. The DKIM alignment path (custom-domain CNAME-delegated DKIM)
DKIM alignment is the load-bearing DMARC pass
mechanism for transactional email. The
custom-domain DKIM pattern is universal across
every ESP: you publish a CNAME (or TXT, in
Postmark's case) at an ESP-specified selector
under your-domain.com, the ESP signs every
outbound message with
d=your-domain.com s=<esp-selector>,
and DKIM aligns with the header
From:.
4.1 How CNAME-delegated DKIM works
- You request domain authentication at the ESP admin UI (typically Settings > Sender Authentication, Domain Settings, or Verified Identities depending on the ESP).
- The ESP generates a key pair internally and
publishes the public key in DNS under its
own control - at e.g.
s1.domainkey.u12345.wl001.sendgrid.net(the actual hostname varies per ESP and per account). - The ESP gives you a CNAME to publish at
<esp-selector>._domainkey.your-domain.compointing to its public-key hostname. - You publish the CNAME at your DNS provider (Cloudflare, Route 53, Google Domains, your registrar's DNS panel, etc.).
- The ESP signs every outbound message with
DKIM-Signature: v=1; a=rsa-sha256; d=your-domain.com; s=<esp-selector>; .... - The receiver fetches the public key by
looking up
<esp-selector>._domainkey.your-domain.com, which CNAMEs to the ESP's hostname, which returns the actual TXT record with the public key. - DKIM verifies successfully with
d=your-domain.com, which aligns with the headerFrom:domain, which makes DMARC pass.
4.2 Why CNAME delegation instead of a direct TXT record
Some ESPs (Postmark, Sendinblue / Brevo) publish the DKIM key as a direct TXT record you copy and paste into DNS. Others (SendGrid, Mailgun, Amazon SES) use CNAME delegation. CNAME delegation has one large operational advantage: the ESP can rotate the underlying key without your involvement. The CNAME target remains stable; the TXT record at the other end of the CNAME chain is what changes when the ESP rotates. Direct-TXT publication requires you to update DNS every time the ESP rotates, which is rarely automated and introduces a rotation-coordination overhead. For high-volume senders CNAME delegation is the operationally safer choice.
4.3 Why DKIM signatures survive forwarding (mostly)
DKIM signatures are computed over the message body (or a canonical form of it - see help_dkim_explained.php for the canonicalization deep dive) and over a selected subset of headers. As long as the body is not modified, the signature survives forwarding intact - so an ESP-signed message that gets forwarded to a personal address still passes DKIM verification at the forwarding hop. SPF on the other hand always breaks on forwarding because the connecting client IP at the forwarding hop is the forwarder's IP, not the original ESP's IP. This is a second reason DKIM is the load-bearing mechanism for transactional email: forwarded messages still pass DMARC via DKIM where they fail via SPF.
4.4 ARC seals preserve forwarded alignment
For mailing-list and aggressive-rewrite forwarders that DO modify the body (subject-line prefixes, footer injection), DKIM verification breaks at the forwarder. ARC (RFC 8617) - the Authenticated Received Chain - lets the forwarder vouch for the original DMARC verdict via an ARC-Seal + ARC-Authentication-Results + ARC-Message-Signature header trio. The receiver evaluates the ARC chain when the direct DMARC fails. Most major receivers (Gmail, Microsoft, Yahoo) honour valid ARC chains. See help_arc_explained.php for the ARC deep dive.
5. Per-ESP DKIM setup walkthroughs
Every ESP exposes the same fundamental custom-domain DKIM pattern through a different UI. The literal selector names and CNAME targets below are verified against each ESP's official documentation as of May 2026. Always confirm the exact values in the ESP admin UI before publishing - some ESPs assign per-account or per-region tokens that differ from the literals here.
5.1 Twilio SendGrid
- Sign in to SendGrid, open Settings > Sender Authentication and click Authenticate Your Domain.
- Select your DNS provider from the dropdown
(Cloudflare, GoDaddy, Route 53, etc.) and
enter your sending domain (e.g.
example.comor the recommended dedicated subdomaintransactional.example.com). - SendGrid generates three CNAMEs:
em####.your-domain.com(custom Return-Path / bounce subdomain - the literal tokenem####is account- specific).s1._domainkey.your-domain.com(first DKIM selector).s2._domainkey.your-domain.com(second DKIM selector - SendGrid rotates between s1 and s2 so both must always resolve).
- Publish all three CNAMEs at your DNS provider, then return to SendGrid and click Verify. SendGrid resolves the CNAMEs and marks the domain authenticated.
- Optionally enable Link Branding
in the same UI to publish two more CNAMEs
(
url####.your-domain.com+54321.your-domain.com) so click-tracking URLs route through your subdomain instead ofsendgrid.net. Link Branding improves deliverability but is not strictly required for DMARC alignment.
Verify DKIM externally:
dig +short cname s1._domainkey.your-domain.com
# expect: s1.domainkey.u12345.wl001.sendgrid.net.
dig +short cname s2._domainkey.your-domain.com
# expect: s2.domainkey.u12345.wl001.sendgrid.net.
dig +short cname em1234.your-domain.com
# expect: u12345.wl001.sendgrid.net.
5.2 Mailgun
- Sign in to Mailgun, open
Sending > Domain Settings,
click Add New Domain, enter
your sending domain (Mailgun strongly
recommends a dedicated subdomain such as
mg.example.comfor SPF-record isolation), and choose your region (US or EU). - Mailgun displays the DNS records to publish:
- SPF:
TXT v=spf1 include:mailgun.org ~allat the domain apex (or the subdomain if using one). - DKIM:
CNAME mailo._domainkey.<domain>pointing tomailo.domainkey.u12345.eu.mailgun.org(newer accounts usemailo; older accounts usemtaorpic- the Mailgun UI shows the literal selector). - MX (optional, only
if you receive mail via Mailgun's
inbound routing):
10 mxa.mailgun.org+10 mxb.mailgun.org. - CNAME tracking
(optional):
email.<domain>pointing tomailgun.org.
- SPF:
- Publish all records, then click Verify DNS Settings - Mailgun resolves and marks the domain Active.
- If using a subdomain, publish DMARC at
_dmarc.mg.example.comas well as (or instead of) the apex; the subdomain-policysp=tag at the apex covers the subdomain when no explicit per-subdomain DMARC record exists.
Verify DKIM externally:
dig +short txt mailo._domainkey.your-domain.com
# expect: a long base64 public key starting with v=DKIM1; k=rsa; p=...
5.3 Amazon SES (Easy DKIM)
- Sign in to the AWS console, switch to the region you send from (us-east-1, eu-west-1, ap-south-1, etc. - SES is region-scoped). Open Amazon SES > Verified identities and click Create identity.
- Choose Domain, enter your
sending domain, tick Use a custom
MAIL FROM domain (recommended -
enables SPF alignment), enter
mail.your-domain.com(or any subdomain), and tick Easy DKIM (the default). - SES generates three CNAMEs of the form
<token>._domainkey.your-domain.compointing to<token>.dkim.amazonses.com. The three tokens are random strings unique to your identity - do not edit them. - For custom MAIL FROM, SES additionally
requires:
MX 10 feedback-smtp.<region>.amazonses.comatmail.your-domain.com.TXT v=spf1 include:amazonses.com ~allatmail.your-domain.com.
- Publish all records at your DNS provider. SES verifies within minutes (occasionally hours during AWS DNS-propagation slowdowns) and marks the identity Verified and DKIM Successful.
- Move your identity out of the SES sandbox via the Request Production Access form - in sandbox mode you can only send to other verified addresses, which is fine for testing but not for production.
Verify DKIM externally:
dig +short cname xxxxxxxxxxxxxxxxxxxx._domainkey.your-domain.com
# expect: xxxxxxxxxxxxxxxxxxxx.dkim.amazonses.com.
# (repeat for each of the 3 tokens shown in the SES console)
5.4 Postmark
- Sign in to Postmark, open your Server, click Sender Signatures > Add Domain or Add Signature, and enter your sending domain.
- Postmark displays the DNS records to publish.
Unlike SendGrid / Mailgun / SES, Postmark
publishes DKIM as a TXT record
(NOT a CNAME) - you copy the full base64
public key from the Postmark UI and paste it
into your DNS provider as the TXT value at
<selector>._domainkey.your-domain.com. The selector is typically the literal date Postmark generated the key (e.g.20240315) or a fixedpmselector for some accounts. - SPF: publish
TXT v=spf1 a mx include:spf.mtasv.net ~allat the domain apex. - Return Path: Postmark handles bounces
internally and does NOT support a custom
Return-Path / bounce subdomain. SPF alignment
therefore relies on the apex SPF record
rather than on a subdomain CNAME -
Postmark's envelope MAIL FROM is
pm-bounces.<your-domain>which IS aligned natively because the bounce domain is at your-domain. - Click Verify Signature - Postmark resolves the DKIM TXT record and marks the signature verified.
Verify DKIM externally:
dig +short txt 20240315._domainkey.your-domain.com
# expect: a long base64 public key starting with v=DKIM1; k=rsa; p=...
5.5 SparkPost
- Sign in to SparkPost, open Configuration > Sending Domains, click Add a Sending Domain, enter your sending domain.
- SparkPost displays a DKIM CNAME at
scph0316._domainkey.your-domain.compointing toscph0316.domainkey.sparkpostmail.com(the literalscph0316is the SparkPost-default selector; enterprise accounts can specify custom selectors). - SPF: SparkPost recommends
TXT v=spf1 include:sparkpostmail.com ~allat the apex. - Custom bounce domain (optional): publish a
CNAME at
bounce.your-domain.compointing tosparkpostmail.com. - Verify - SparkPost resolves DNS within minutes.
5.6 Mailjet
- Sign in to Mailjet, open Senders & Domains, click Add a sending domain, enter your sending domain.
- Mailjet displays:
- SPF:
TXT v=spf1 include:spf.mailjet.com ?allat the apex. - DKIM: a CNAME at
mailjet._domainkey.your-domain.compointing tomailjet.domainkey.mailjet.com.
- SPF:
- Click Check now. Mailjet verifies within minutes.
5.7 Sendinblue / Brevo
- Sign in to Brevo (formerly Sendinblue), open Senders & IPs > Domains, click Add a domain, enter your sending domain.
- Brevo displays:
- Brevo code: a TXT
record at the apex of the form
brevo-code:<hash>for domain ownership verification. - SPF:
TXT v=spf1 include:spf.brevo.com -allat the apex (Brevo recommends-allnot~all). - DKIM: a TXT record
at
mail._domainkey.your-domain.comcontaining the full base64 public key Brevo generated. - DMARC: a TXT record
at
_dmarc.your-domain.com- Brevo will recommend a starter policy ofv=DMARC1; p=none; rua=mailto:dmarc@brevo.combut you should pointrua=at YOUR mailbox so DMARC Analyzer ingests the reports, not Brevo.
- Brevo code: a TXT
record at the apex of the form
- Publish all four records, then click Authenticate this domain.
5.8 Resend
- Sign in to Resend, open Domains, click Add Domain, enter your sending domain and choose the region (us-east-1 or eu-west-1).
- Resend displays:
- SPF:
TXT v=spf1 include:amazonses.com ~allatsend.your-domain.com(Resend uses Amazon SES infrastructure under the hood, so the SPF include is amazonses.com). - DKIM: a CNAME at
resend._domainkey.your-domain.compointing toresend.amazonses.com(single selector, no rotation pair). - MX (for bounces):
10 feedback-smtp.<region>.amazonses.comatsend.your-domain.com. - DMARC: a TXT record
at
_dmarc.send.your-domain.comwith at minimumv=DMARC1; p=none; rua=mailto:dmarc-reports@your-domain.com.
- SPF:
- Publish all records and click Verify DNS Records.
5.9 MailerSend
- Sign in to MailerSend, open Domains, click Add Domain, enter your sending domain.
- MailerSend displays:
- SPF:
TXT v=spf1 include:_spf.mlsend.com ~allat the apex. - DKIM: two CNAMEs at
mlsend._domainkey.your-domain.comandmlsend2._domainkey.your-domain.compointing to MailerSend's key infrastructure. - Tracking (optional):
CNAME at
email.your-domain.comfor click-tracking links. - Custom Return-Path:
CNAME at
mta.your-domain.comfor SPF alignment via custom bounce domain.
- SPF:
- Click Verify Domain.
5.10 Mandrill (Mailchimp transactional)
- Sign in to Mailchimp, open the Transactional API / Mandrill product, then open Settings > Domains & Tracking.
- Mandrill uses the same domain
authentication CNAMEs as the Mailchimp
marketing product:
- SPF:
TXT v=spf1 include:spf.mandrillapp.com ?allat the apex. - DKIM: two CNAMEs at
k1._domainkey.your-domain.comandk2._domainkey.your-domain.compointing todkim.mandrillapp.comanddkim2.mandrillapp.com. - Tracking (optional):
CNAME at
mail.your-domain.com.
- SPF:
- Click Verify Domain.
5.11 Other ESPs
Beyond the ten ESPs documented above, the same
universal pattern applies. Look for the
Domain Authentication /
Sender Authentication /
Verified Identities /
Domains page in the ESP's
admin UI, publish the CNAMEs (or TXT records)
they generate, verify with
dig +short cname <selector>._domainkey.your-domain.com,
and proceed to DMARC publication. The 10
ESPs above cover roughly 90 percent of the
transactional-email volume in production
deployments; the remaining 10 percent
(Pepipost / Netcore, Elastic Email,
SocketLabs, SMTP2GO, Mailtrap, IBM Cloud Email
Service, etc.) follow the same pattern with
different selector literals.
6. Return-Path / custom bounce domain configuration (SPF alignment)
DKIM alignment is sufficient for DMARC to pass. SPF alignment is the bonus second path. For senders pursuing the Feb 2024 Google / Yahoo bulk-sender requirements, having BOTH SPF and DKIM aligned is the recommended configuration - Google explicitly mentions both in its Email sender guidelines.
6.1 The custom Return-Path mechanic
The ESP sets the envelope MAIL FROM
(also called the bounce address or Return-Path)
to a subdomain you control instead of one the
ESP controls. You publish a CNAME at the
subdomain pointing to the ESP's bounce-handling
hostname:
- SendGrid:
em####.your-domain.com->u12345.wl001.sendgrid.net(theem####token is generated per-account). - Mailgun: the dedicated
sending subdomain itself
(
mg.your-domain.com) acts as the bounce domain - no separate Return-Path CNAME needed. - Amazon SES: the custom MAIL
FROM domain
(
mail.your-domain.com) with the MX + SPF records described in section 5.3. - SparkPost:
bounce.your-domain.com->sparkpostmail.com. - MailerSend:
mta.your-domain.comas Custom Return-Path.
Postmark, Mailjet, Brevo, Resend, and Mandrill
do not expose a separate custom Return-Path
configuration - their default envelope MAIL FROM
is either pre-aligned (Postmark via
pm-bounces.your-domain.com) or
relies on DKIM alignment alone.
6.2 Verifying SPF alignment after custom Return-Path setup
After publishing the custom Return-Path CNAME
and waiting for DNS propagation, send a test
message and inspect the
Authentication-Results header at
the receiver. The expected line shape is:
Authentication-Results: mx.google.com;
dkim=pass header.i=@your-domain.com header.s=s1 header.b="...";
spf=pass (google.com: domain of bounces+1234@em1234.your-domain.com
designates 167.89.123.45 as permitted sender)
smtp.mailfrom=bounces+1234@em1234.your-domain.com;
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=your-domain.com
The key indicators are
smtp.mailfrom=...your-domain.com
(envelope domain is a subdomain of your
organizational domain) and
dmarc=pass. The
Email Header
Analyzer on DMARC Analyzer parses this
block and highlights alignment passes / failures
via includes/EmailHeaderParser.php.
7. Subdomain segmentation strategy
The dedicated-subdomain pattern is the recommended architecture for transactional email at scale. Three motivations:
7.1 Reputation isolation
Receivers track sender reputation per
organizational domain AND per subdomain. A
transactional subdomain
(transactional.example.com,
mail.example.com,
mg.example.com) accrues
high-engagement reputation (password resets and
2FA codes get clicked, receipts get archived,
and complaint rate stays low). Corporate mail
(example.com apex via Workspace /
M365) accrues normal-engagement reputation.
Marketing mail
(news.example.com via SendGrid
Marketing or Mailchimp) accrues
lower-engagement, higher-complaint reputation.
Isolating each class behind its own subdomain
means one campaign's bad day does not drag the
transactional subdomain's reputation down -
transactional deliverability stays stable.
7.2 Independent DMARC policy via np= / sp=
RFC 7489 defines sp=
(subdomain-policy) which sets the DMARC policy
for all subdomains of the organizational
domain. RFC 9091 (formerly DMARCbis) introduces
np= (non-existent-subdomain-policy)
which sets policy for subdomains that do NOT
have their own DMARC record. The
tag
deep dive covers each. Practical use:
- At the apex, publish
v=DMARC1; p=reject; sp=reject; np=reject; rua=mailto:dmarc@your-domain.comonce corporate and transactional alignment are both clean. - During ESP onboarding, publish an explicit
per-subdomain DMARC record at
_dmarc.transactional.your-domain.comwithp=noneso the apexsp=rejectdoes not block your in-flight ESP setup. - Once the transactional subdomain is clean,
remove the subdomain-specific record and let
the apex
sp=tag take over - one canonical apex DMARC record covers every subdomain.
7.3 SPF 10-DNS-lookup limit relief
RFC 7208 section 4.6.4 caps SPF DNS lookups at
10 per evaluation. include:
mechanisms each consume one lookup
(plus the lookups in the included record).
include:_spf.google.com is 3
lookups; include:sendgrid.net is
1-2; include:mailgun.org is 1;
include:amazonses.com is 1. A
sender with Workspace + SendGrid + Mailgun + SES
at the apex hits 6-7 lookups before any custom
infrastructure. Dedicated subdomains per ESP
keep each SPF record under the limit:
; apex: corporate (Workspace) only
example.com. TXT "v=spf1 include:_spf.google.com ~all"
; transactional subdomain: SendGrid only
transactional.example.com. TXT "v=spf1 include:sendgrid.net ~all"
; marketing subdomain: Mailgun only
news.example.com. TXT "v=spf1 include:mailgun.org ~all"
7.4 Operational clarity
Each team owns a subdomain. The corporate security team owns the apex DMARC record; the application team owns the transactional subdomain; the marketing team owns the marketing subdomain. DNS-record changes are independent. Aggregate-report investigation is scoped to a subdomain. ESP onboarding does not require coordinating with security to ramp the apex.
8. Step-by-step rollout (SPF -> DKIM -> p=none -> ramp -> p=reject)
- Pick a sending domain
(recommended: a dedicated subdomain such as
transactional.your-domain.comormail.your-domain.com). - Configure ESP custom-domain DKIM
per section 5 - publish the CNAME (or TXT)
at the ESP-specified selector, verify with
dig, click Verify in the ESP UI. - Configure custom Return-Path / bounce subdomain per section 6 - optional but recommended for full alignment coverage.
- Publish SPF at the sending
domain with the ESP's include mechanism.
Verify with
dig +short txt <domain>. - Send a test message to a
Gmail / Microsoft / Yahoo address you
control. Open the message and view the
Authentication-Resultsheader (in Gmail: Show Original; in Outlook web: ... > View > View message source). Verifydkim=passwithheader.i=@your-domain.comand ideallyspf=passwithsmtp.mailfrom=...your-domain.com(or any aligned envelope). - Publish DMARC at p=none at
_dmarc.your-domain.com(or at_dmarc.transactional.your-domain.comfor a subdomain-only rollout). Minimum record:v=DMARC1; p=none; rua=mailto:dmarc-reports@your-domain.com. - Wait 2-6 weeks and read aggregate (RUA) reports via DMARC Analyzer. Verify alignment pass rate is 95+ percent for the ESP's source IPs. Investigate any gaps via the source IP detail view + report detail view.
- Advance to p=quarantine for
4-12 weeks, with optional
pct=25throughpct=100ramp. Monitor for ANY new alignment failures from senders that newly appeared in aggregate reports. - Advance to p=reject once
quarantine has been clean for one full
sender-rotation cycle (typically 4 weeks).
Keep
pctat 100 (the default). - Maintain: read aggregate reports weekly per the monitoring guide. Investigate any new source-IP drift via the sender-inventory diff workflow documented there.
9. Bounce handling and feedback loops
9.1 Why bounce handling matters for DMARC
Bounce handling is operationally adjacent to DMARC because uncorrected bounces drive your complaint rate up, which drives your sender reputation down, which causes receivers to bulk-folder or delay your mail even when DMARC is correctly aligned. The Feb 2024 Google / Yahoo bulk-sender requirements set a complaint rate cap of 0.1 percent (one complaint per 1000 delivered messages). Exceeding that cap is a deliverability blocker.
9.2 ESP bounce-handling endpoints
Every major ESP exposes a webhook or HTTP API for bounce notifications. Subscribe your application to receive bounces and suppress addresses immediately after a hard bounce or spam complaint.
- SendGrid:
Settings > Mail Settings >
Event Webhook with events
bounce,dropped,spamreport,unsubscribe. - Mailgun:
Sending > Webhooks with
events
permanent_fail,temporary_fail,complained,unsubscribed. - Amazon SES: configure an
SNS topic per Configuration Set with
event types
Bounce,Complaint,Reject. The SES Feedback Forwarding option is OFF by default for production accounts - use SNS. - Postmark:
Servers > <your-server>
> Webhooks with events
Bounce,SpamComplaint,SubscriptionChange.
9.3 Feedback loops (FBL)
Major receivers (Yahoo, AOL / Verizon Media, Microsoft via SNDS) expose a Feedback Loop that forwards spam complaints back to senders. ESPs subscribe to these on your behalf and surface complaints via the bounce-handling webhook. You do NOT need to register your domain with each receiver's FBL individually; that is the ESP's responsibility. Verify your ESP's FBL coverage in the ESP's documentation - SendGrid, Mailgun, SES, Postmark all automatically subscribe.
9.4 Suppression-list hygiene
Keep an internal suppression list of every address that has ever hard-bounced or complained. Re-attempting delivery to those addresses drives complaint rate up and reputation down. Every ESP also maintains a suppression list internally - SES, SendGrid, Mailgun, and Postmark all block sends to addresses on their internal list. Cross-check your application's list against the ESP's list periodically.
10. Dedicated IP vs shared IP authentication implications
10.1 Shared IP pools
By default every ESP places new accounts on a shared IP pool - your outbound mail leaves alongside hundreds or thousands of other ESP customers' mail from the same IP. Shared IP advantages: zero IP warmup required, the ESP handles reputation maintenance, you can ramp volume up and down freely. Shared IP disadvantages: your sender reputation is influenced by every other customer on the pool, so a high-complaint customer in the same pool can degrade your deliverability.
DMARC alignment works identically on shared and
dedicated IPs - the IP does not change DKIM /
SPF alignment. The Authentication-Results header
will show the shared IP in the
spf=pass verification, but that is
irrelevant to alignment.
10.2 Dedicated IPs
Available on most ESPs (SendGrid Advanced, Mailgun Foundation, SES dedicated IPs, SparkPost Enterprise, Postmark Dedicated IP add-on) for an additional fee. Dedicated IPs must be warmed up - typically 30-60 days of progressively increasing volume so the receiver reputation engines learn your IP behaves well. Volume schedules vary; Mailgun and SES publish recommended warmup curves.
Dedicated IP advantages: your reputation is yours alone, large senders can hit higher receiver-side throughput limits. Disadvantages: warmup is mandatory; small senders (under 100k messages/month) cannot accumulate enough volume to maintain a reputation signal and end up worse off than on shared. Dedicated IP only makes sense above roughly 500k messages/month sustained.
10.3 Multiple dedicated IPs and IP rotation
Above 1M messages/month some senders run multiple dedicated IPs with weighted rotation - each IP carries a fraction of the load, receivers track each one independently, and isolation between transactional / marketing / notification traffic classes becomes practical. SendGrid, Mailgun, SES all support multi-IP pools with weighted routing.
DMARC alignment is unaffected by IP rotation. Each IP signs with the same DKIM key (because the key is per-domain, not per-IP) and the envelope MAIL FROM remains constant.
11. Multi-ESP estates
Many senders run multiple ESPs in parallel - SendGrid for marketing, Postmark for transactional, AWS SES for notification mail. The DMARC alignment surface scales linearly: each ESP needs its own custom-domain DKIM CNAMEs, each ESP signs with its own selector, and DMARC requires only ONE valid aligned signature per message to pass.
11.1 DKIM selector coexistence
Publishing
s1._domainkey.your-domain.com +
s2._domainkey.your-domain.com
(SendGrid) +
mailo._domainkey.your-domain.com
(Mailgun) +
<token>._domainkey.your-domain.com
(Amazon SES, three of them) all at the same
time is fine - each ESP signs messages with its
own selector, the receiver looks up only the
selector named in each message's
DKIM-Signature header
s= field, and unrelated selectors
do not interfere.
11.2 SPF aggregation (or subdomain segmentation)
SPF is the bottleneck. Aggregating all ESPs into a single apex SPF record hits the 10-DNS-lookup limit fast. The recommended architecture is subdomain segmentation per section 7 - one ESP per subdomain, one SPF record per subdomain, each well under the limit.
If you must aggregate at the apex (e.g. because
your stack uses a single From: domain across
all sender categories), use an SPF flattening
service that periodically resolves each
include: mechanism into the
underlying ip4 / ip6 ranges and republishes
the resulting flat record. SPF flattening
services include EasyDMARC SPF Flattening,
dmarcian SPF Surveyor,
Cloudflare Email Routing SPF Flattening,
and self-hosted scripts. Note: flattening
introduces fragility because the ESP's IP
ranges change over time without notice, so the
flattening service must run on a schedule
(daily or weekly) and the operator must monitor
it. The recommended approach is subdomain
segmentation, not flattening.
11.3 Multi-ESP failover
For deliverability resilience some senders route the same message class through two ESPs - primary on SendGrid, failover on Amazon SES. DMARC alignment works the same way: both ESPs sign with custom-domain DKIM, both pass DMARC independently, and the receiver verifies whichever signature is present. The failover logic lives in your application or in an SMTP routing layer (Postal, Haraka, etc.); it is transparent to DMARC.
12. Common transactional-email DMARC mistakes
- Trusting SPF=pass without alignment. The most common cause of transactional-email DMARC failure. SPF passes for the ESP's bounce domain but does not align with your header From:. Custom-domain DKIM is the fix.
- Publishing only one of the SendGrid
DKIM selectors. SendGrid rotates
between
s1._domainkeyands2._domainkey; if only one resolves, messages signed with the other selector fail DKIM verification. Always publish both. - Forgetting to enable DKIM at the ESP sub-account level. Large SendGrid / Mailgun deployments use sub-accounts (one per business unit or per product line); DKIM is configured per sub-account, not globally. Publishing the parent account's CNAMEs does not authenticate the sub-account's outbound mail.
- Putting the DMARC record at the
wrong subdomain.
_dmarc.transactional.example.comcoversFrom: foo@transactional.example.comonly.From: foo@example.comfrom the SAME ESP requires DMARC at_dmarc.example.comwithsp=ornp=set appropriately - the per-subdomain record does not cover the apex. - Ramping to p=reject before clean alignment. The 2-6 week p=none observation period is not optional. Skipping it means legitimate transactional mail bounces or quarantines at receivers, which users notice immediately (missing password resets are escalations).
- Forgetting the SPF 10-DNS-lookup
limit when adding the second ESP.
Workspace + SendGrid = ~5 lookups; adding
Mailgun + SES pushes you past 10 and SPF
breaks with
permerror. Subdomain segmentation (section 7) avoids this. - Sending from a domain that does not
match the ESP-authenticated domain.
If you authenticate
example.comin SendGrid but send withFrom: alerts@notify.example.com, DKIM signs withd=example.com(in relaxed alignment that aligns OK with notify.example.com), but if SendGrid's config requires strict alignment or pinsd=notify.example.comyou need to authenticate the subdomain separately. - Pointing rua= at the ESP's
recommended fallback (
dmarc@brevo.com,dmarc@mailgun.org, etc.). The ESP receives the reports instead of you. Always pointrua=at your mailbox or your DMARC analytics platform (DMARC Analyzer, dmarcian, EasyDMARC, Valimail) so the reports flow to you. - Leaving SPF at
?allor+all. The neutral (?all) and pass-all (+all) qualifiers tell receivers to ignore SPF authentication outcomes, which is the opposite of what you want. Always use~all(softfail) or-all(hardfail). For DMARC-enforced domains-allis strictly correct - if your SPF includes are exhaustive, mail from any other IP should hardfail. - Disregarding bounce notifications. Hard bounces and spam complaints not removed from your sender list drive complaint rate up and reputation down. Reputation degradation cascades into deliverability degradation even when DMARC is perfectly aligned. Subscribe to the ESP's bounce webhook per section 9.
13. Troubleshooting
13.1 ESP marks domain as Pending / Verification Failed
Most common cause: DNS propagation delay. CNAME
records typically propagate in 1-15 minutes but
some DNS providers cache for hours. Wait, then
re-click Verify. If still failing, inspect the
record value with dig and compare
against the ESP's expected value byte-for-byte.
13.2 Aggregate reports show DKIM=fail at high rate
Three likely causes:
- The ESP's CNAME chain is broken. Confirm
with
dig +trace <selector>._domainkey.your-domain.com- the trace should resolve through the ESP's hostname to a TXT record containingv=DKIM1; k=rsa; p=.... If the CNAME chain terminates at a NXDOMAIN, the ESP rotated keys and the CNAME target is stale - re-authenticate the domain in the ESP UI. - Sub-account DKIM not enabled (SendGrid / Mailgun multi-account deployments). Configure DKIM at the sub-account level in the ESP UI.
- Message body modified after signing. Mailing lists / forwarders / spam filters sometimes add footers or modify subjects. DKIM canonicalization (see help_dkim_explained.php) determines tolerance. ARC (section 4.4) recovers DMARC alignment through aggressive forwarders.
13.3 Aggregate reports show DMARC=fail with SPF=pass + DKIM=pass
This signals an alignment problem, not an
authentication problem. Inspect the report's
auth_results block:
- If
spf.domainis the ESP's bounce domain (bounces.sendgrid.net, bounce.mailgun.org, amazonses.com): SPF passed but did not align. Configure custom Return-Path (section 6) OR rely on DKIM alignment - check the next bullet. - If
dkim.domainis the ESP's signing domain (sendgrid.net, mailgun.org, amazonses.com): DKIM passed but did not align - the ESP signed with its ownd=instead of yours. Configure custom-domain DKIM (section 5) and verify the ESP UI shows the domain as authenticated.
13.4 New IP appears in aggregate reports with high volume
Either an ESP added IPs to its outbound pool (legitimate drift - update your sender inventory) or an unauthorized sender is spoofing your domain (file spoofing - investigate via the source IP detail view + report detail view). The monitoring guide documents the weekly sender-inventory-diff workflow that routes new IPs to one of the two outcomes.
13.5 ESP says DKIM is verified but receiver shows DKIM=fail
The ESP verifies the CNAME at publication time
but does not continuously re-verify. If the
CNAME target hostname later becomes unreachable
(the ESP rotates infrastructure, your DNS
provider has an outage, etc.), the receiver's
DKIM lookup fails. Re-test the CNAME chain with
dig +trace, contact ESP support
if the target appears stale.
13.6 Diagnostic toolkit
- Email Header Analyzer
(header_analyzer.php) -
parses
Authentication-ResultsandDKIM-Signatureheaders viaincludes/EmailHeaderParser.php; identifies the signing domain, the selector, and the alignment verdict for any single message. The first tool to reach for when an end user reports a missing transactional email. - Domain Security Checker
(domain_checker.php) -
live DNS lookups for SPF, DKIM, DMARC,
BIMI, MTA-STS, TLS-RPT, CAA via
includes/DnsChecker.php; verifies every CNAME chain. - DNS Record Generator (dns_generator.php) - generates syntactically-correct DMARC, SPF, DKIM, BIMI, MTA-STS, TLS-RPT, CAA records when onboarding a new ESP.
- Aggregate report drill-down
(reporter_detail.php +
source_ip_detail.php +
reports_detail.php) -
navigates RFC 7489 aggregate reports
ingested via
includes/DmarcParser.php. - Forensic / failure-sample drilldown
when individual messages are spoofed -
forensic reports ingested via
includes/ForensicReportParser.php. digat the command line:dig +short cname <selector>._domainkey.your-domain.com,dig +short txt _dmarc.your-domain.com,dig +trace <selector>._domainkey.your-domain.com.
14. Frequently asked questions
- How do I set up DMARC for SendGrid?
- Five steps. (1) Sign in to SendGrid, open Settings > Sender Authentication, click Authenticate Your Domain, choose your DNS provider, and enter your sending domain (e.g. example.com or transactional.example.com). (2) SendGrid generates a set of CNAMEs typically rooted at em.<your-domain>, s1._domainkey.<your-domain>, and s2._domainkey.<your-domain>. Publish all three CNAMEs at your DNS provider (Cloudflare, Route 53, Google Domains, etc.) - the em.<your-domain> CNAME is the custom Return-Path for SPF alignment, the s1 and s2 CNAMEs are the rotating DKIM key pair for DKIM alignment. (3) Return to SendGrid and click Verify; SendGrid resolves the CNAMEs and marks the domain authenticated. (4) Publish DMARC at _dmarc.<your-domain> with v=DMARC1; p=none; rua=mailto:dmarc-reports@<your-domain> to start collecting aggregate reports. (5) After 2-6 weeks of clean reports advance p=quarantine then p=reject. SendGrid signs every message with s=s1 or s=s2 alternating, so both selectors must resolve at all times - never delete one without rotating to the new pair first.
- How do I set up DMARC for Mailgun?
- Five steps. (1) Sign in to Mailgun, open Sending > Domain Settings, click Add New Domain, enter your sending domain (e.g. mg.example.com or transactional.example.com - Mailgun strongly recommends a dedicated subdomain), and choose your region (US or EU). (2) Mailgun displays the DNS records you must publish: a TXT record at the domain apex for SPF (v=spf1 include:mailgun.org ~all - or include:mailgun.org and your own ip4: ranges if you also send from your own infrastructure), a CNAME at mailo._domainkey.<your-domain> (newer DKIM selector; older Mailgun accounts use mta._domainkey or pic._domainkey - check the Domain Settings page for the literal name), and optionally MX records if you also receive mail via Mailgun. (3) Publish all records at your DNS provider, then click Verify DNS Settings - Mailgun resolves the records and marks the domain Active. (4) Publish DMARC at _dmarc.<your-domain> (or _dmarc.mg.<your-domain> for the subdomain) with v=DMARC1; p=none; rua=mailto:dmarc-reports@<your-domain>. (5) After 2-6 weeks of clean reports advance to p=quarantine then p=reject.
- How does Amazon SES Easy DKIM work for DMARC?
- Amazon SES Easy DKIM publishes a 2048-bit DKIM key automatically when you verify a sending identity (a domain or a subdomain). Five steps. (1) Sign in to the AWS console, open SES > Verified identities, click Create identity, choose Domain, enter your sending domain, and tick Use a custom MAIL FROM domain (recommended). (2) Tick Easy DKIM (the default) - SES generates three CNAMEs of the form <token>._domainkey.<your-domain> pointing to <token>.dkim.amazonses.com (the tokens are random strings unique to your identity, do not edit them). The custom MAIL FROM option requires an additional MX record (10 feedback-smtp.<region>.amazonses.com) and a TXT SPF include (v=spf1 include:amazonses.com ~all) at your chosen MAIL FROM subdomain. (3) Publish all 3 DKIM CNAMEs + MAIL FROM records at your DNS provider, then wait for AWS to verify (typically minutes, occasionally hours). (4) Publish DMARC at _dmarc.<your-domain> with v=DMARC1; p=none; rua=mailto:dmarc-reports@<your-domain>. (5) Advance to enforcement after clean reports. Easy DKIM auto-rotates keys every quarter; the CNAMEs do not change - they always point to SES, which controls the underlying private key behind the scenes.
- How do I set up DMARC for Postmark?
- Postmark uses Sender Signatures (per-address) and per-domain DKIM. Four steps. (1) Sign in to Postmark, open the Server you send from, click Sender Signatures > Add Domain or Add Signature, enter your sending domain (e.g. example.com or transactional.example.com). (2) Postmark displays the DKIM TXT record - a long base64 public key at <selector>._domainkey.<your-domain> where <selector> is typically the literal date Postmark generated the key (e.g. 20240101 or pm._domainkey). Publish the TXT record at your DNS provider exactly as shown (Postmark publishes the actual public key as a TXT value, NOT a CNAME - this is a deliberate design choice for verification simplicity). Also publish a TXT SPF include at the domain apex: v=spf1 a mx include:spf.mtasv.net ~all. (3) Click Verify Domain in Postmark - it resolves the DKIM TXT record and marks the signature verified. (4) Publish DMARC at _dmarc.<your-domain> with v=DMARC1; p=none; rua=mailto:dmarc-reports@<your-domain>, then advance to enforcement after clean reports.
- Why does my transactional email pass SPF but fail DMARC?
- Almost always because SPF passes for the ESP infrastructure but the envelope MAIL FROM domain (5321.From) does not align with your visible header From: (5322.From). ESPs typically rewrite the envelope MAIL FROM to an ESP-controlled bounce domain (bounces.sendgrid.net for SendGrid, bounce.mailgun.org for Mailgun, <region>.amazonses.com for Amazon SES) so the ESP can handle delivery failures. SPF checks that bounce domain against the ESPs SPF record, which passes - but DMARC requires alignment of the SPF-authenticated domain with the header From: domain, which fails because the bounce domain does not match your-domain.com. Fix: configure custom-domain DKIM at the ESP (CNAMEs at <selector>._domainkey.<your-domain> pointing to the ESPs key infrastructure) so DMARC aligns via DKIM regardless of envelope rewriting. Optionally also configure a custom Return-Path / bounce subdomain (em.<your-domain> CNAME to the ESPs bounce hostname) so SPF aligns too, but DKIM alignment is the load-bearing mechanism for transactional email.
- Should I use a dedicated subdomain for transactional email?
- Yes - the dedicated-subdomain pattern (e.g. transactional.example.com, mail.example.com, mg.example.com) is the recommended architecture for transactional email at scale. Three benefits. (1) Reputation isolation: transactional traffic (high engagement, low complaint rate) builds a distinct sender reputation from corporate mail (employees emailing externally, often with attachments) and marketing mail (lower engagement, higher complaint rate). Receivers track reputation per subdomain, so isolating each class of mail prevents one bad day from degrading the others. (2) Independent DMARC policy via the np= / sp= tags: the organizational domain can ramp p=reject while a subdomain remains at p=none during ESP onboarding. (3) Operational clarity: every team can verify alignment for their subdomain without coordinating with the security team owning the apex. Cost: requires the ESP to authenticate the subdomain (one set of CNAMEs per subdomain) and your DNS provider to publish per-subdomain records. Tradeoff is worth it above ~5000 transactional messages/day or whenever the Feb 2024 Gmail / Yahoo bulk-sender thresholds apply.
- How do I handle DMARC when I use multiple ESPs at the same time?
- Each ESP needs its own custom-domain DKIM CNAMEs published in your DNS, all under distinct selectors. SendGrid uses s1._domainkey and s2._domainkey; Mailgun uses mailo._domainkey; Amazon SES uses three random tokens; Postmark uses a date-named selector. Publishing all four sets of CNAMEs simultaneously is fine - each ESP signs messages with its own selector, and DMARC requires only ONE valid DKIM signature aligned with the header From: domain to pass. The receiver looks up only the selector named in the DKIM-Signature header s= field of each message, so unrelated selectors do not interfere. For SPF: include all ESPs in a single SPF record at the apex, but watch the 10-DNS-lookup limit (RFC 7208 section 4.6.4) - SendGrid + Mailgun + Amazon SES + your own MTA already consumes 4-6 lookups before counting redirects. Use a dedicated subdomain per ESP (transactional.example.com on SendGrid, marketing.example.com on Mailgun, etc.) to keep each SPF record under the limit and isolate reputation.
- Do I need DMARC at p=reject if I only send transactional email?
- Yes, especially for transactional email. Three reasons. (1) Transactional messages (password resets, 2FA codes, magic links, payment receipts) are high-value spoofing targets because they trigger user action - a forged password-reset email lands in the same inbox as a legitimate one, and only DMARC enforcement blocks the forgery at receiver level. (2) The Feb 2024 Google / Yahoo bulk-sender requirements explicitly mandate DMARC at p=quarantine or stricter for senders above 5000 messages/day to Gmail / Yahoo Mail; transactional senders routinely exceed this threshold. (3) At p=none receivers DELIVER spoofed messages to the inbox - DMARC at p=none gives you reporting visibility but provides zero blocking. Operators should treat p=reject as the production-ready end state and treat p=none as a temporary alignment-debug stop on the rollout path. The DMARC Analyzer dashboard walks the operator through the ramp via the rollout guide help_dmarc_policy_rollout.php and the troubleshooting loop help_dmarc_troubleshooting.php.
16. Start verifying your transactional email alignment now
DMARC Analyzer ingests aggregate
(rua) reports via
includes/DmarcParser.php and surfaces
every per-source-IP alignment outcome on the
dashboard (index.php). The
per-source-IP drilldown
(source_ip_detail.php) shows which
ESPs are aligning cleanly and which are not; the
per-reporter drilldown
(reporter_detail.php) shows which
receivers (Google, Microsoft, Yahoo, La Poste,
Mail.ru) are receiving your authenticated
transactional mail. The
header_analyzer.php tool (built on
includes/EmailHeaderParser.php)
diagnoses single-message alignment when a user
reports a missing password reset. The
domain_checker.php tool (built on
includes/DnsChecker.php) live-resolves
every CNAME chain so you can confirm a new ESP's
DKIM setup before sending the first message.
Forensic (ruf) failure samples land
via upload.php through
includes/ForensicReportParser.php
for spoofing investigation.