5 May 2026 · 15 min read
Mailgun is a developer-first sending API, and that shapes everything about how you authenticate it. Unlike Google Workspace or Microsoft 365, where you bolt authentication onto an existing mailbox domain, Mailgun pushes you to send from a dedicated sending subdomain such as mg.yourdomain.com. That single design choice quietly answers most of the SPF, DKIM and alignment questions people get stuck on, and it also creates a specific trap: you authenticate the subdomain perfectly, your Mailgun dashboard turns green, and yet your DMARC record at the organisational domain still does not see aligned mail the way you expect. This guide is about getting all of that right, with Mailgun's actual records, so you can take the domain to p=reject without dropping a single legitimate message.
It assumes you control your DNS (Cloudflare, Route 53, GoDaddy, wherever it lives) and that you send at least some mail through Mailgun, whether that is transactional receipts from an app, password resets, or full marketing campaigns. The DNS host barely matters. What matters is the subdomain model, the exact records Mailgun gives you, and the order you tighten things in.
Why Mailgun uses a sending subdomain, and why it matters
When you add a domain in Mailgun, it strongly steers you towards a subdomain like mg.yourdomain.com rather than your bare yourdomain.com. This is not arbitrary. The subdomain gets its own SPF record, its own DKIM key, and its own MX records pointing at Mailgun so bounces and complaints can be processed. Isolating sending traffic on a subdomain has real benefits:
- The subdomain builds its own sending reputation, separate from the human mailboxes on your root domain. A reputation problem on bulk mail does not poison your one-to-one business email.
- The MX records Mailgun wants (
mxa.mailgun.organdmxb.mailgun.org) live on the subdomain, so they never collide with the MX records that route your real inbound mail at the root. - The custom return-path (envelope sender) sits naturally under the subdomain, which is what gives you SPF alignment, covered below.
You can add your root domain to Mailgun instead, and sometimes that is the right call (for example, you only send transactional mail and you want the visible From to be noreply@yourdomain.com with everything on the apex). But be deliberate about it, because adding Mailgun's MX records to your root domain would break your existing inbound mail. For the vast majority of setups, the subdomain is correct. Throughout this guide the working example is mg.yourdomain.com; substitute your real subdomain.
Before changing anything, it is worth knowing where you stand. Run your sending domain through the DMARC checker, the SPF checker and the DKIM checker so you can see which of the records below are already present and which are missing.
Step 1: the exact SPF record for Mailgun
SPF authorises the servers allowed to send mail using your domain in the envelope sender (the Return-Path / MAIL FROM), not the visible From address. For Mailgun, the include is:
include:mailgun.org
On the sending subdomain, the SPF record Mailgun asks you to publish is a TXT record at mg.yourdomain.com:
mg.yourdomain.com TXT "v=spf1 include:mailgun.org ~all"
A few things that bite people specifically with Mailgun:
- This record goes on the subdomain, not the root. A very common mistake is pasting
include:mailgun.orginto the root domain's existing SPF record because that is where you already had an SPF record for Google or Microsoft. If you send through Mailgun onmg.yourdomain.com, the relevant SPF record is the one atmg.yourdomain.com. The root SPF record governs mail whose envelope sender is the root domain, which is a different thing. include:mailgun.orgcosts one DNS lookup. That is cheap, but it still counts against the SPF ten-lookup limit if you ever consolidate senders onto one domain. On a dedicated subdomain that only sends through Mailgun, you have plenty of headroom. The glossary entry on the 10-lookup limit explains the mechanics if you are combining Mailgun with other senders on the same host.- Use
~allwhile you build confidence. Soft fail tells receivers that anything not listed is suspicious but should not be hard-rejected on SPF alone. Once DMARC reporting confirms every Mailgun source is accounted for, you can tighten to-allon the subdomain.
If you genuinely send Mailgun mail from your root domain (apex) alongside, say, Google Workspace, then you do merge the includes into the root's single SPF record, like this:
yourdomain.com TXT "v=spf1 include:_spf.google.com include:mailgun.org ~all"
That is one record with two includes, which is correct. What is never correct is two separate TXT records both starting v=spf1 on the same host, which produces a permerror and fails SPF entirely. The SPF checker counts your lookups and flags duplicate records for you, and for the wider picture of combining vendors see SPF records for common providers.
Step 2: enable and publish DKIM for Mailgun
DKIM is the mechanism that actually carries DMARC alignment for most Mailgun setups, because Mailgun's return-path uses its own bounce handling and SPF often will not align by default (more on that in Step 3). So DKIM is not optional here, it is the load-bearing part.
When you add a domain in Mailgun and open its DNS settings, Mailgun generates a DKIM key for you automatically and shows you a TXT record to publish. The host looks like this:
k1._domainkey.mg.yourdomain.com TXT "k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ..."
The important Mailgun-specific details:
- The selector is typically
k1. Mailgun's current dashboard provisions a DKIM selector namedk1, so the full host isk1._domainkey.mg.yourdomain.com. Older Mailgun accounts and some documentation reference different selectors such asmxorsmtp, and you may see a second key for DKIM rotation appear later. Always publish the exact host Mailgun shows in your dashboard rather than copying a selector from a tutorial, because the selector is what tells receivers which key to look up. - The value may start with
k=rsa; p=...rather thanv=DKIM1; .... Mailgun sometimes omits the leadingv=DKIM1;tag. That is valid;v=DKIM1is optional and defaults correctly when absent. Publish the value exactly as given. - Long TXT values must be handled correctly. A 2048-bit DKIM key exceeds the 255-character limit for a single DNS string, so it has to be split into multiple quoted strings inside one TXT record. Most modern DNS panels (including Cloudflare) do this automatically when you paste the value. If your provider rejects a long value, split it into 255-character chunks within the same record. The glossary entry on DKIM selectors explains how the
_domainkeyhost is structured.
After you publish the record, go back to the Mailgun domain settings and click the button to verify DNS (Mailgun polls your DNS and marks each record as verified once it can see it). DNS propagation can take minutes to a few hours depending on TTL. You can watch it with the DNS propagation checker.
Do not trust the green tick alone
Mailgun showing the DKIM record as verified means the published key matches what Mailgun expects. It does not, by itself, prove that outbound mail is being signed with a domain that aligns to your From address. Send a real test message to an external mailbox you control, open the raw headers, and find the DKIM-Signature header. You are looking for:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mg.yourdomain.com;
s=k1; ...
The d= value is the signing domain and s= is the selector. For Mailgun on a subdomain, d=mg.yourdomain.com is exactly what you want, because it will align (in relaxed mode) with a From address at the root domain. You can confirm the published key independently with the DKIM checker by entering mg.yourdomain.com and the selector k1. The DKIM record guide and the DKIM product page go deeper on signing.
Step 3: custom return-path and the alignment problem
This is the part that is genuinely Mailgun-specific and the part that most generic guides get wrong, so it is worth slowing right down.
DMARC does not just ask "did SPF or DKIM pass?". It asks "did SPF or DKIM pass and align with the domain in the visible From address?". There are two kinds of alignment:
- SPF alignment compares the domain in the hidden Return-Path (the envelope sender, the thing SPF actually checks) against your From domain.
- DKIM alignment compares the
d=domain in the DKIM signature against your From domain.
A message passes DMARC if either one aligns. You only need one of the two. Here is how that plays out on Mailgun.
By default, Mailgun sends with an envelope sender (Return-Path) on a Mailgun-controlled bounce domain, something under mailgun.org. SPF passes for that domain, because Mailgun's servers are authorised in mailgun.org's SPF. But that domain is mailgun.org, not your domain, so under DMARC the SPF result does not align with your From address. This is the single most misunderstood thing about authenticating Mailgun: SPF can show a green pass and still contribute nothing to DMARC, because the pass is for the wrong domain.
You have two ways to get an aligned pass:
- Rely on aligned DKIM. Because you published the DKIM key on
mg.yourdomain.comand Mailgun signs withd=mg.yourdomain.com, DKIM aligns with a root-domain From in relaxed mode. For most people this is enough on its own, and it is robust because DKIM survives forwarding where SPF often does not. If you do nothing else, make sure DKIM is solid. - Configure a custom return-path so SPF also aligns. Mailgun lets you set the Return-Path to your own subdomain rather than its bounce domain. When you add the domain to Mailgun, this is what the MX records and the
mailgun.orgSPF onmg.yourdomain.comare for: with the subdomain set up fully, the envelope sender becomes something likebounce@mg.yourdomain.com, SPF is evaluated againstmg.yourdomain.com, and that does align (relaxed) with a root From. Now both mechanisms align, which is the belt-and-braces position.
In practice, the way you achieve SPF alignment on Mailgun is by completing the full subdomain setup, including the MX records:
mg.yourdomain.com MX 10 mxa.mailgun.org
mg.yourdomain.com MX 10 mxb.mailgun.org
Those MX records let Mailgun receive and process bounces on your subdomain, which is what makes the custom return-path possible. If you skip the MX records because "I only send, I do not receive", you give up SPF alignment and you are relying entirely on DKIM. That can be fine, but know that you are doing it.
One sharp edge: if your From address uses the root domain (receipts@yourdomain.com) while everything is signed and bounced on mg.yourdomain.com, alignment works in relaxed mode because the subdomain shares the organisational domain. It does not work in strict mode (adkim=s / aspf=s), which requires an exact match. Keep alignment relaxed unless you have a specific reason, and read DMARC alignment explained for worked examples. If your From address is itself on the subdomain (receipts@mg.yourdomain.com), even strict alignment works, which is one reason some teams send entirely from the subdomain.
The tracking CNAME and why it does not affect DMARC
Mailgun also asks you to publish a tracking CNAME, typically:
email.mg.yourdomain.com CNAME mailgun.org
This rewrites click and open tracking links to run through your own domain, which improves the appearance of links and avoids the generic Mailgun tracking host. It has nothing to do with SPF, DKIM or DMARC alignment, and a missing tracking CNAME will never cause an authentication failure. Publish it for link branding, but do not chase it when you are debugging a DMARC problem.
Step 4: publish DMARC at p=none and collect reports
With SPF and DKIM correct, publish a DMARC record. DMARC lives at the organisational level, so the record goes on _dmarc.yourdomain.com even though your sending is on a subdomain (subdomains inherit the organisational policy unless you publish a separate one). Start at p=none, which is monitoring only and changes nothing about delivery:
_dmarc.yourdomain.com TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; fo=1; adkim=r; aspf=r"
What the tags do:
p=nonemeans monitor and take no action. You must start here. You cannot see what enforcement would break until reports arrive.rua=mailto:...is where aggregate reports go, daily XML summaries from each receiver.fo=1requests failure reporting when either mechanism fails, for finer diagnostics where supported.adkim=randaspf=rset relaxed alignment, which is what letsmg.yourdomain.comalign with a root-domain From.
Build a tailored record with the DMARC generator, confirm it is live with the DMARC checker, and see DMARC RUA and RUF reports for what the two report types contain.
Do not point rua at a human inbox
Aggregate reports are raw XML, and a domain that sends through Mailgun plus a mailbox provider will receive dozens a day from Google, Microsoft, Yahoo and others. A person cannot read these usefully. You can drop a single report into the DMARC report analyzer to inspect it by hand, but for an ongoing picture you want something that aggregates every report into one view of sources, pass rates and alignment. That is what /monitor and the analytics product do, including alerting you when a record changes or a new sender appears.
Step 5: read the reports and close the gaps
Leave the domain at p=none for two to four weeks. The aggregate reports will sort every sender into three buckets.
- Your Mailgun traffic. It should show DKIM aligned with
d=mg.yourdomain.com, and SPF aligned too if you completed the custom return-path. If Mailgun mail is failing alignment, the cause is almost always one of: the DKIM record not published or mistyped, strict alignment set by accident, or the From address sitting on a domain that does not share the organisational domain with the signing subdomain. Fix that before going further. - Other legitimate senders you forgot. Reports routinely surface a forgotten newsletter tool, a billing system, a CRM or a help desk still sending as your domain. Each needs its own SPF authorisation and ideally its own aligned DKIM. Mailgun reports often reveal that you are sending the same transactional mail through two services, which you can then consolidate.
- Genuine spoofing. Mail you do not recognise, failing authentication from servers you do not control. This is exactly what enforcement will stop, but only once the first two buckets are clean.
The discipline is simple and non-negotiable: do not advance the policy until every legitimate source in your reports produces an aligned pass. Enforcement acts on alignment, not on intent. Anything legitimate still failing when you move to enforcement will be quarantined or rejected. DMARC common mistakes covers the failure patterns to watch for.
Step 6: ratchet to quarantine, then reject
Once reports show legitimate mail passing cleanly and the only failures are mail you do not recognise, start tightening. Move in stages and use pct to roll out gradually.
Begin by quarantining a sample of failing mail:
_dmarc.yourdomain.com TXT "v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@yourdomain.com; adkim=r; aspf=r"
That sends a quarter of failing mail to spam and leaves the rest unchanged. Watch the reports for a week. If nothing legitimate is caught, raise pct to 50, then 100:
_dmarc.yourdomain.com TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc@yourdomain.com; adkim=r; aspf=r"
Sit at full quarantine for a couple of weeks, keep watching, then move to the final policy:
_dmarc.yourdomain.com TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=r; aspf=r"
At p=reject, mail that fails DMARC is refused at the receiving server, never reaching inbox or spam. This is the goal, and it is the policy Gmail and Yahoo's bulk-sender rules push everyone towards (see /requirements for the current thresholds). Once you are at reject and confident every Mailgun source is accounted for, you can also tighten the subdomain's SPF from ~all to -all. The staged rollout is covered further in /how/enforce and the policy progression glossary.
Subdomain policy and Mailgun
Because Mailgun sends from a subdomain, the sp tag is worth understanding. By default the subdomain inherits your p policy. If you want the subdomain to enforce on its own schedule, or you have other subdomains that never send mail, set sp explicitly. A common, safe stance once you trust your Mailgun setup is to keep the organisational policy at p=reject and let the sending subdomain inherit it, since by then mg.yourdomain.com is producing aligned passes. For non-sending subdomains, an explicit sp=reject shuts down a spoofing route. See DMARC subdomain policy.
Mailgun-specific gotchas
A handful of issues come up repeatedly on Mailgun domains and nowhere else:
- EU vs US region. Mailgun runs separate US and EU infrastructure. If your account is in the EU region, you manage the domain in the EU control plane and your API base URL differs, but the DNS records (SPF include
mailgun.org, DKIM selector, MXmxa/mxb.mailgun.org) are the same. The trap is sending through the wrong regional endpoint, which can cause silent delivery issues unrelated to authentication. Confirm your region matches where the domain was created. - Sandbox domains do not authenticate. Every Mailgun account starts with a
sandboxXXXX.mailgun.orgdomain for testing. You cannot add custom DNS to it and it can only send to authorised recipients. Authentication only matters once you add and verify your own domain. Do not try to make the sandbox align. - The From domain must match where you authenticated. If you set up
mg.yourdomain.comin Mailgun but your application sends with a From address ofnoreply@othbrand.com, none of this alignment applies, because DMARC is evaluated against the From domain. Send from the domain you authenticated. - DKIM key rotation. Mailgun may offer a second DKIM key for rotation. When you rotate, publish the new selector's TXT record before retiring the old one so there is no signing gap. See DKIM key rotation.
- Re-verify after DNS edits. After any change, give propagation time and click verify again in Mailgun rather than assuming. The DNS record checker and DNS propagation checker save you from chasing stale-cache phantoms.
Optional next steps: MTA-STS and BIMI
Once you are authenticating Mailgun mail cleanly and enforcing DMARC, two further layers are worth knowing about.
MTA-STS is unrelated to Mailgun's outbound authentication; it protects mail coming into your domain by telling sending servers to require TLS. It is a sensible companion to DMARC for any serious domain. See the MTA-STS checker and the MTA-STS guide.
BIMI displays your brand logo next to authenticated mail in supporting clients, but only once you are at p=quarantine or p=reject with aligned DKIM, which you now have. Because your Mailgun mail is signed on mg.yourdomain.com, pay attention to which domain your BIMI record sits on relative to the From address you actually send from. The BIMI checker and the BIMI product page cover the requirements, including the Verified Mark Certificate that Gmail expects.
The practical takeaway
Authenticating Mailgun is mostly about respecting its subdomain model. Publish SPF (v=spf1 include:mailgun.org ~all) on the sending subdomain, not the root. Publish the DKIM key Mailgun generates at k1._domainkey.mg.yourdomain.com exactly as shown, and verify with a real test that mail is signed with d=mg.yourdomain.com. Understand that Mailgun's default return-path means SPF will not align on its own, so either lean on aligned DKIM or complete the custom return-path with the mxa/mxb.mailgun.org MX records to get SPF aligned too. Then publish DMARC at p=none on _dmarc.yourdomain.com, read the aggregate reports until every Mailgun source and every other legitimate sender passes with alignment, and ratchet through quarantine with pct to p=reject. Done in that order, you reach full enforcement with no email outage and a domain that can no longer be spoofed.
If you would rather not spend a month reading XML and editing DNS, that is exactly the work we take off your plate. The hosted DMARC product sets up and watches SPF, DKIM and MTA-STS across your sending domains (Mailgun included), manages the staged rollout to reject, and gives you continuous monitoring with alerts when anything changes. To start right now for free, run your sending domain through the DMARC checker and see exactly which of the records above you still need.