Decoding M365 DKIM Fails: selector1, selector2, and the `onmicrosoft` Trap
Microsoft 365's CNAME-based DKIM setup is clever, but its silent fallbacks and key rotation logic create subtle `dkim=fail` scenarios that stump even seasoned admins.

You just opened your DMARC aggregate report. There's a splash of red—a spike in DKIM failures from IPs you recognize as Microsoft's own egress gateways. But you enabled DKIM for your custom domain months ago. It was working. The portal shows a green checkmark. So what's actually happening?
This is a familiar story for anyone managing a Microsoft 365 tenant. The platform’s DKIM implementation is more complex than the simple public-private key pair defined in RFC 6376. It’s a managed service, built on DNS CNAMEs and automated rotation, with a fallback behavior that silently sabotages DMARC alignment.
Forget the simple setup guides. We're going to pull apart the headers, trace the DNS records, and understand why your M365 DKIM setup is failing in the wild. This isn't just about passing a check; it's about ensuring your domain's reputation and deliverability are actually protected.
What Microsoft 365 Actually Signs With
The first thing to internalize is that Microsoft 365 is always signing email, from the moment you create your tenant. The question is, with which identity?
The `.onmicrosoft.com` Safety Net
By default, every email leaving your tenant gets a DKIM signature. But it doesn't use your company's domain. Instead, it uses your tenant's initial domain: `<yourtenant>.onmicrosoft.com`. You can see this in the `DKIM-Signature` header's `d=` tag—it will point right back to Microsoft's infrastructure.
Why does this matter? Because a valid DKIM signature is useless for DMARC if it's for the wrong domain. DMARC, as defined in RFC 7489, requires *alignment*. The domain in the `From:` header (`yourcompany.com`) must match the domain in the `DKIM-Signature`'s `d=` tag. When they don't match, the DKIM check fails DMARC evaluation, even if the signature itself is cryptographically valid. This is the root cause of countless DMARC headaches.
Activating Your Custom Domain
When you follow the Microsoft 365 DKIM setup guide, you aren't creating a key. You are publishing two special CNAME records that delegate DKIM authority for your domain to Microsoft. The goal is to command the M365 signing infrastructure to switch from using `d=<yourtenant>.onmicrosoft.com` to `d=yourcompany.com` for all outbound mail. When this works, your outbound email achieves DMARC alignment, and receiving mail servers see your messages as authenticated.
`selector1` and `selector2`: More Than Just Names
The core of M365's managed DKIM system lies in two innocuous-looking DNS records you're told to create. They are always named `selector1` and `selector2`.
These aren't TXT records containing a public key, which is the standard method for self-hosted mail servers. Instead, they are CNAME records. They act as pointers, aliasing your domain's DKIM records to a domain that Microsoft controls. The records look like this:
selector1._domainkey.yourcompany.com CNAME selector1-yourcompany-com._domainkey.yourtenant.onmicrosoft.com
When a receiving mail server needs to verify a signature from your domain, it looks for the public key at `selector1._domainkey.yourcompany.com`. Your DNS tells it, "I don't have the key directly, but you can find it over at this Microsoft-controlled address." This lets Microsoft manage the entire key lifecycle without you ever having to generate, handle, or rotate private keys.
The Key Rotation Dance
So why two selectors? It’s for zero-downtime key rotation. Microsoft can decide to rotate keys at any time for security reasons. Let's say they are currently signing your mail using `selector1`. To rotate, they'll generate a new key pair. The new public key is published on their end, served via the `selector2` CNAME you already have in place. After waiting for DNS to propagate globally, they switch their signing machines to use the new private key and stamp emails with `s=selector2` in the DKIM header. The old `selector1` key can then be decommissioned. No action is needed from you, and mail flow is never interrupted.
When Good Signatures Go Bad: Decoding the Failure
When everything is configured correctly, this system works well. But several failure modes can crop up, leading to the confusing DMARC reports that started this whole mess.
The Mismatched `d=` Domain Trap
This is, by far, the most common issue. For some reason, DKIM signing for `yourcompany.com` gets disabled or fails to initialize. M365, trying to be helpful, falls back to its default behavior: signing with `d=<yourtenant>.onmicrosoft.com`. The receiving server sees an email from `user@yourcompany.com` with a valid signature for the wrong domain. The cryptographic check passes, but the DMARC alignment check fails.
The `Authentication-Results` header on a received email tells the whole story. You'll see a verdict like this:
Authentication-Results: spf=pass (sender IP is ...) smtp.mailfrom=yourcompany.com; dkim=pass (signature was verified) header.d=yourtenant.onmicrosoft.com; dmarc=fail action=reject header.from=yourcompany.com; — Example Authentication-Results Header
See it? `dkim=pass` but `dmarc=fail`. The `header.d` doesn't match `header.from`. This can happen if the custom domain was removed and re-added, or if the initial configuration was never fully enabled via PowerShell with `Set-DkimSigningConfig -Identity yourcompany.com -Enabled $true`.
Body Hash Failures from MTA Modifications
Another classic is the `dkim=fail (body hash did not verify)` error. This isn't unique to M365, but it's a frequent problem. DKIM signs a hash of the email body (`bh=` tag). If anything downstream—a mailing list, a security gateway, or even a forwarder that adds a "[EXTERNAL]" tag to the subject—modifies the body or certain headers, the hash no longer matches. The signature is broken. This frequently happens with forwarded calendar invites or automated system alerts that get rewritten in transit.
Don't Trust the Portal; Verify the Headers
That green checkmark in the M365 Defender portal simply confirms that your CNAME records exist and point to the right place. It does not confirm that Microsoft is actually *using* them to sign your mail correctly. You have to verify that yourself.
The process is simple. Send an email from your M365 account to an external mailbox you control, like a personal Gmail account. Don't send it internally, as mail may not follow the same path. Once received, view the original message source (in Gmail, click the three dots and "Show original").
First, find the `DKIM-Signature` header. Check two tags: `d=yourcompany.com` and `s=selector1` (or `selector2`). If `d=` shows your `.onmicrosoft.com` domain, you've found the fallback problem. If the header is missing entirely, DKIM isn't being applied at all.
Next, find the `Authentication-Results` header. This is the receiver's final judgment. Look for the `dkim=` entry. It should say `pass` and confirm the `header.d` is your custom domain. If it shows `temperror` (temporary error), the receiving server couldn't fetch your public key via DNS. A `permerror` (permanent error) might indicate a malformed record. `none` means no signature was found. And `fail` can mean a body hash mismatch or an invalid signature.
Your DMARC Data Is a Goldmine for DKIM Bugs
Triaging individual emails is fine for spot checks, but DMARC aggregate reports are where you'll find systemic problems. These XML reports, sent by receivers, provide a complete picture of how the world sees your domain's email.
When you parse one of these reports, you aren't just looking for SPF or DKIM pass/fail counts. You're hunting for patterns. Filter for records where the primary DKIM evaluation failed. Now, look at the extra detail provided for the DKIM check. Is the domain listed in the `<domain>` tag inside the `<dkim>` result consistently your `<yourtenant>.onmicrosoft.com` address? Are the source IPs Microsoft Online IPs?
If yes, you have your smoking gun. This tells you that a significant volume of your outbound mail is failing DMARC alignment because it's being signed by the wrong M365 identity. This pattern is nearly impossible to spot without DMARC reporting, as the emails are still being delivered (at least until you move to a `p=reject` policy).
Fixing the Problem: Back to PowerShell
If you've confirmed your custom domain isn't being used for DKIM signing, the fix is almost always in Exchange Online PowerShell. The GUI often doesn't expose the true state or provide the controls needed.
First, connect to Exchange Online PowerShell. Then, run `Get-DkimSigningConfig` to see the status of all configured domains. You will likely see that the entry for your custom domain has `Enabled: False`.
To fix it, you simply enable it for your domain. If your selectors haven't been rotated, you may need to rotate them to force the system to pick up the new configuration.
# Enable DKIM signing for your domain
Set-DkimSigningConfig -Identity yourcompany.com -Enabled $true
# Force a key rotation if needed
Rotate-DkimSigningConfig -Identity yourcompany.com
After running these commands, wait a few minutes and then repeat the validation test by sending a new email to an external account. Check the headers again. You should now see the `d=yourcompany.com` tag, and DMARC should pass with flying colors.
The takeaway
Microsoft 365's DKIM system favors automation over transparency. It's designed to be a hands-off utility, but its failure modes are subtle and can completely undermine your DMARC posture. Don't assume a green check in a portal means your domain is secure. The only source of truth is the email header and the aggregate data from receivers.
The most common culprit is the fallback to the `.onmicrosoft.com` domain, a ghost in the machine that creates DMARC alignment failures masquerading as DKIM problems. Regularly analyze your outbound headers and DMARC reports to catch this. Constantly monitoring DMARC data is critical, and raw XML is a pain. Tools like ours at MailSleuth.AI can correlate these M365-specific DKIM failures with source IPs and user reports, cutting triage time from hours to minutes.
We dissect phishing campaigns and email infrastructure so you don't have to.


