Table of Contents
Every major mailbox provider now enforces authentication for bulk senders and treats unauthenticated mail with suspicion, so a Microsoft 365 tenant without DKIM and DMARC will see messages land in junk folders even from a clean IP. The three records do different jobs: SPF lists which servers may send for the domain, DKIM signs each message so tampering and forgery are detectable, and DMARC tells receivers what to do when neither check aligns with the visible From address, while sending reports back to you. Exchange Online supports all three; only DKIM needs to be switched on, and it is the step most tenants skip.
Short answer: Publish a TXT record at the domain root of v=spf1 include:spf.protection.outlook.com -all, adding any other services that send as the domain. In the Defender portal under Email authentication settings » DKIM, select the domain, copy the two selector CNAME records, publish them in DNS, then enable signing, or do the same with New-DkimSigningConfig and Set-DkimSigningConfig -Enabled $true in Exchange Online PowerShell. Finally publish _dmarc TXT with v=DMARC1; p=none; rua=mailto:dmarc@example.com and tighten to quarantine or reject once reports show alignment.
SPF for Exchange Online
Only one SPF record may exist per domain, so merge Microsoft’s include with anything else that sends on the domain’s behalf, such as a ticketing system or a marketing platform:
example.com. IN TXT "v=spf1 include:spf.protection.outlook.com include:_spf.ticketvendor.example -all"
Stay under the ten DNS lookup limit; each include counts, and nested includes count too. Use -all for a hard fail once you are confident the list is complete, and ~all during a transition. If an on-premises server or a cPanel host still relays mail as the domain, add its address with ip4: rather than routing everything through Exchange Online. A cPanel-hosted domain with mail moving to Microsoft 365 also needs its local mail routing set to remote in cPanel » Email Routing so the server stops accepting mail for itself.
DKIM signing
Exchange Online signs with two rotating selectors, selector1 and selector2, whose public keys live under Microsoft’s domain; you publish CNAMEs pointing at them. The names include your tenant’s initial onmicrosoft.com domain, so retrieve them from the portal or PowerShell rather than guessing:
Connect-ExchangeOnline
New-DkimSigningConfig -DomainName example.com -Enabled $false
Get-DkimSigningConfig -Identity example.com | Format-List Selector1CNAME, Selector2CNAME
Publish the two CNAME records exactly as returned, for example selector1._domainkey.example.com pointing at selector1-example-com._domainkey.tenant.onmicrosoft.com. Wait for DNS to propagate, then enable:
Set-DkimSigningConfig -Identity example.com -Enabled $true
Get-DkimSigningConfig -Identity example.com | Format-List Enabled, Status, LastChecked
The portal path is Microsoft Defender » Email & collaboration » Policies & rules » Threat policies » Email authentication settings » DKIM. If enabling fails with a message that the CNAME cannot be found, the records are wrong or not yet visible; check with dig CNAME selector1._domainkey.example.com. Rotate keys every year or so with Rotate-DkimSigningConfig, which switches to the other selector without downtime.
DMARC policy
Start in monitoring mode so nothing is rejected while you discover every legitimate sender:
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; fo=1; adkim=r; aspf=r"
Aggregate reports arrive daily as XML from each receiving provider; feed them to a report analyser rather than reading them raw. After a few weeks with no unexplained failures, move to p=quarantine with pct=25 and increase, then p=reject. Subdomains inherit the policy unless sp= says otherwise; explicitly set sp=reject on domains that never send from subdomains. If mail is forwarded through a cPanel server on the way in, its SRS setting must be on or SPF breaks for forwarded messages, though DKIM survives forwarding and keeps DMARC passing.
Verify with headers
Send a message from the tenant to a mailbox on another provider and inspect the raw headers. The Authentication-Results header should show spf=pass, dkim=pass with the domain and selector, and dmarc=pass. In Exchange Online the Message Trace under the Exchange admin centre confirms the message left with a DKIM signature, and Get-DkimSigningConfig shows Status as Valid. External checks:
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short CNAME selector1._domainkey.example.com
The common pitfall is a DNS provider that appends the domain to CNAME targets, producing a record ending in .onmicrosoft.com.example.com; paste the target with a trailing dot or check the provider’s handling. Another is enabling DKIM before the CNAMEs resolve, which leaves the config in a disabled state that needs re-enabling later. For the equivalent cPanel-side setup of a domain that keeps mail on the server, see SPF, DKIM and DMARC in cPanel DNS.
Microsoft 365 SPF DKIM DMARC at a glance

Official documentation: Microsoft 365 documentation, RFC 7489 (DMARC), RFC 7208 (SPF).
Related guides: Microsoft 365 shared mailbox vs distribution group vs Microsoft 365 Group · MailBaby DKIM transport signing explained: why some mail shows “via mailbaby.net” · Choosing a VPS for a cPanel or DirectAdmin server in 2026.
Frequently asked questions
Does Exchange Online DKIM also sign mail sent by third-party services using my domain?
No. Exchange Online only signs messages that pass through it. Services that send directly must be configured with their own DKIM selector on your domain, and their sending hosts must be in SPF.
How long does it take for DKIM to become active in Microsoft 365?
Once the CNAME records resolve publicly, enabling takes a minute or two. DNS propagation is the variable part and can be anywhere from minutes to a day depending on the provider’s TTLs.
Can I undo a DMARC reject policy if legitimate mail is being rejected?
Yes. Change p=reject back to p=none or p=quarantine in the _dmarc TXT record; receivers pick up the new policy at their next DNS lookup, usually within the record’s TTL.