Skip to content

Microsoft 365 DKIM Setup, Step by Step

Short answer

Microsoft 365 DKIM needs two CNAME records — selector1._domainkey and selector2._domainkey — pointing into your tenant’s onmicrosoft.com domain, and then signing switched on in the Defender portal. Publishing the CNAMEs alone does nothing; enabling before they resolve returns an error.

Check it yourself
DKIM Checker
Find and validate DKIM keys — selector discovery included

Two things trip people up on this setup. First, Microsoft 365 does not sign with your custom domain until you explicitly enable it — a fresh tenant signs outbound mail as <tenant>.onmicrosoft.com, which authenticates fine but does not align with a From: header on your own domain, so DMARC fails. Second, the enable step validates the DNS records and refuses to run if they are not resolvable yet. Order matters: publish, wait, enable.

DKIM Checker
Find and validate DKIM keys — selector discovery included

Why two selectors?

Microsoft rotates DKIM keys on its own schedule without asking you to touch DNS. Two published selectors make that safe: at any moment one key is actively signing and the other is the standby. When rotation happens, signing moves to the standby selector — whose key is already resolvable — and a new key is generated behind the first selector.

If you publish only selector1, everything works right up until the first rotation, at which point messages are signed with selector2 and receivers cannot find the key. The symptom is dkim=fail (no key for signature) appearing overnight on a setup that had been fine for months. Publish both.

What do the CNAMEs look like?

Both point into your tenant’s initial onmicrosoft.com domain. The general shape is:

Type:  CNAME
Name:  selector1._domainkey
Value: selector1-<domain-with-dashes>._domainkey.<tenant>.onmicrosoft.com

Type:  CNAME
Name:  selector2._domainkey
Value: selector2-<domain-with-dashes>._domainkey.<tenant>.onmicrosoft.com
The two records, in the shape Microsoft generates them

The <domain-with-dashes> part is your custom domain with dots replaced by dashes. Microsoft’s own domain is a live example you can inspect right now:

dig +short CNAME selector1._domainkey.microsoft.com
selector1-microsoft-com._domainkey.microsoft.onmicrosoft.com.

dig +short CNAME selector2._domainkey.microsoft.com
selector2-microsoft-com._domainkey.microsoft.onmicrosoft.com.

# Querying TXT follows the CNAME and returns the actual key
dig +short TXT selector2._domainkey.microsoft.com
selector2-microsoft-com._domainkey.microsoft.onmicrosoft.com.
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
microsoft.com — selector1 and selector2 delegated to the tenant
Do not hand-construct these values from the pattern. Copy them from the Defender portal for your tenant — a .mail.protection.outlook.com region suffix or a hyphenated form you guessed wrong produces a CNAME that resolves to nothing, and the enable step will reject it.

For a domain with a hyphen in it, note that Microsoft’s transformation only replaces dots. my-company.co.uk becomes my-company-co-uk, which is ambiguous if you try to reverse it — another reason to copy rather than derive.

Publishing the records

Both are ordinary CNAME records in whatever DNS provider hosts your zone. Points worth knowing:

  • The Name field is selector1._domainkey on providers that append your zone automatically (Cloudflare, Namecheap, most registrars). Entering the fully-qualified name there produces selector1._domainkey.example.com.example.com.
  • On Cloudflare, set proxy status to DNS only (grey cloud). Cloudflare will not proxy a _domainkey record anyway, but check it — a proxied CNAME returns Cloudflare IPs, not the delegation.
  • TTL of 3600 is fine. You are not going to change these.
  • A CNAME cannot coexist with any other record at the same name. If a TXT record is already sitting at selector1._domainkey from a previous mail provider, delete it first.
  • If the zone is DNSSEC-signed, nothing special is needed — check the zone validates with the DNSSEC checker if you are troubleshooting resolution failures.

Verify both resolve before touching the portal. The CNAME lookup does this in the browser, or from a shell:

for s in selector1 selector2; do
  echo -n "$s: "
  dig @1.1.1.1 +short CNAME "$s._domainkey.example.com"
done
Both must return a target before you enable signing

Enabling signing

DKIM for custom domains is managed in the Microsoft Defender portal under email authentication settings, and can also be driven with Exchange Online PowerShell. Microsoft has moved this page around more than once, so navigate by searching for DKIM in the portal rather than following a memorized path — and check Microsoft’s current documentation if the layout differs from what a guide describes.

# Exchange Online PowerShell
Connect-ExchangeOnline -UserPrincipalName [email protected]

# See current state and the selector CNAMEs to publish
Get-DkimSigningConfig -Identity example.com | Format-List

# Create the config if the domain has never been set up
New-DkimSigningConfig -DomainName example.com -Enabled $false

# Enable signing once both CNAMEs resolve
Set-DkimSigningConfig -Identity example.com -Enabled $true
The PowerShell equivalent of the portal toggle

The enable operation performs its own DNS check. If it fails with a message about the CNAMEs not being found, the records are genuinely not resolvable from Microsoft’s vantage point yet — either they were published in the wrong host field, or you are inside the negative-cache window. Wait and retry rather than editing anything.

Verifying it works

Publication and enablement are two separate facts, and you should confirm both.

CheckHowExpected
CNAMEs publisheddig +short CNAME selector1._domainkey.example.comA ...onmicrosoft.com. target
Key resolvabledig +short TXT selector1._domainkey.example.comA record containing p= with base64 data
Signing enabledGet-DkimSigningConfig -Identity example.comEnabled : True
Actually signingSend a test message, read the raw headersDKIM-Signature with d=example.com
Aligned for DMARCRead Authentication-Results on the delivered messagedkim=pass [email protected] and dmarc=pass

That last row is the one that matters. Send a message to an external mailbox you control and check the delivered headers — the email header analyzer will parse them, or read them directly:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com;
        s=selector1; h=from:to:subject:date; bh=...; b=...

Authentication-Results: mx.google.com;
       dkim=pass [email protected] header.s=selector1;
       spf=pass smtp.mailfrom=example.com;
       dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=example.com
What a correctly configured tenant produces

If d= still shows <tenant>.onmicrosoft.com, signing for the custom domain is not enabled — the CNAMEs being present is not enough. If the signature is present with d=example.com but the receiver reports failure, work through body hash did not verify, since a transport rule or a disclaimer appliance appending a footer after signing is the usual cause in Exchange environments.

Exchange Online transport rules that append disclaimers run in a defined order relative to signing. If DKIM breaks on every outbound message after you add a disclaimer rule, that rule is the change to look at first.

Troubleshooting the common failures

SymptomMost likely causeWhat to do
Portal refuses to enable, "CNAME not found"Records not resolvable from Microsoft’s side yet, or the wrong host fieldVerify with dig @1.1.1.1 +short CNAME selector1._domainkey.example.com, then retry after the negative-cache window
d= still shows <tenant>.onmicrosoft.comCNAMEs published but signing never enabled for the custom domainRun Get-DkimSigningConfig and confirm Enabled : True
dkim=fail (no key for signature) after months of workingMicrosoft rotated to a selector you never publishedPublish the missing second CNAME — both must exist permanently
DNS provider rejects the CNAMEA leftover TXT or CNAME already occupies that nameDelete the stale record; CNAMEs cannot coexist with other types at the same name
dkim=fail (body hash did not verify)A transport rule or appliance modifies the body after signingSee body hash did not verify
DKIM passes but dmarc=failSigning domain does not match the From: domainConfirm d= is your custom domain, not the tenant or a vendor domain

A note on hybrid and third-party routing: if outbound mail leaves through an on-premises Exchange server or a third-party security gateway rather than directly from Exchange Online, the signature is applied by whichever system Microsoft hands the message to last. Mail that never traverses Exchange Online is not signed by it at all, regardless of what the portal says. Trace an actual message’s Received: chain before concluding the configuration is wrong.

The rest of the authentication set

Frequently asked questions

Do I need DKIM if Microsoft already signs with onmicrosoft.com?
Yes, if you send From: your custom domain. The default signature uses d=<tenant>.onmicrosoft.com, which authenticates but does not align with a From: header on example.com, so it contributes nothing to DMARC. Custom-domain signing is what makes DKIM useful for you.
Why does the portal refuse to enable DKIM?
It validates that both selector CNAMEs resolve before it will turn signing on. If they were just published, resolvers may still be serving a cached negative answer for the SOA minimum TTL. Confirm with dig against a public resolver, then retry after the cache window.
Can I publish the DKIM key as a TXT record instead of a CNAME?
Not for the standard Microsoft 365 flow — the CNAME delegation is what lets Microsoft rotate keys without your involvement. Publishing a TXT record with a key you generated would only work if you were bringing your own key, which is not how the built-in configuration operates.
Which selector is actually signing my mail right now?
Read the s= tag in the DKIM-Signature header of a message you just sent. It will say selector1 or selector2, and it changes when Microsoft rotates. That is normal and is exactly why both must stay published permanently.
Do I need to do this for every domain in the tenant?
For every domain you send mail From:. Each accepted domain gets its own pair of selector CNAMEs and its own enable step. A domain you only receive mail on does not need DKIM signing.
What if a TXT record already exists at selector1._domainkey?
Delete it. A CNAME cannot coexist with any other record type at the same name, and most DNS providers will reject the CNAME or produce an invalid zone. Leftover selector records from a previous mail provider are a common cause of this.

Last updated: 2026-09-01