7 June 2026 · 12 min read
DMARC for Microsoft 365: SPF, DKIM and enforcement done properly
If your organisation runs email through Microsoft 365 (Exchange Online), you already have most of the moving parts you need for strong email authentication. What you almost certainly do not have, unless someone has done the work deliberately, is a published SPF record that actually covers every sending source, DKIM signing switched on with Microsoft's two rotating selectors, and a DMARC policy that has been moved off p=none to enforcement without quietly breaking newsletters, ticketing systems or your accounts team's invoicing tool.
This guide walks through exactly that, in order, for a Microsoft 365 tenant. It is written for the person who owns DNS and the Exchange admin centre, and it assumes you want to reach p=reject safely rather than just tick a compliance box. Along the way you can sanity-check each step with the free diagnostic tools, and if you would rather not babysit reports for weeks, the done-for-you service does the staged rollout for you.
A quick orientation before we start. Microsoft 365 is unusual in two helpful ways. First, it publishes a single SPF include that covers all of Exchange Online's outbound IP ranges, so your SPF record stays short. Second, its DKIM implementation uses CNAME records pointing back into Microsoft's infrastructure, which means Microsoft rotates the underlying keys for you and you never paste a 2048-bit public key into DNS by hand. Both of these reduce the usual SPF and DKIM headaches, but they introduce their own quirks that trip people up. We will call those out as we go.
Why the default Microsoft 365 setup is not enough
When you onboard a domain to Microsoft 365, the setup wizard typically asks you to add an MX record, an SPF (TXT) record and sometimes Autodiscover. That is enough to send and receive mail. It is not enough to stop someone spoofing your domain.
By default a fresh tenant signs outbound mail with DKIM using Microsoft's shared onmicrosoft.com domain, not your own vanity domain. That signing exists, but the signature is d=yourtenant.onmicrosoft.com, which does not align with the From: address your recipients see (@yourcompany.com). For DMARC, alignment is the whole game: a message passes DMARC only when SPF or DKIM authenticates and the authenticated domain lines up with the visible From: domain. Microsoft's default DKIM does not align, so until you enable DKIM for your custom domain you are relying entirely on SPF alignment, and SPF breaks the moment a message is forwarded.
So the real default state of a typical Microsoft 365 domain is: SPF present but often incomplete, DKIM technically signing but not aligned to your domain, and no DMARC record at all. That is a domain anyone can spoof. The fix is the three sections that follow.
You can confirm your current state in under a minute. Run your domain through the DMARC checker to see whether a policy exists and what it says, the SPF checker to see your current include chain and lookup count, and the DKIM checker against Microsoft's selectors (more on those shortly).
Step 1: Get SPF right for Exchange Online
SPF tells the world which servers are allowed to send mail using your domain in the MAIL FROM (envelope sender). For Microsoft 365, the single include you need is spf.protection.outlook.com. A minimal, correct record looks like this:
v=spf1 include:spf.protection.outlook.com -all
That covers all normal outbound mail flow through Exchange Online. The -all at the end is a hard fail, meaning any server not listed should be treated as unauthorised. Some administrators are nervous about -all and use ~all (soft fail) instead. For DMARC purposes the difference is smaller than people think, because DMARC reads SPF as pass or fail regardless of the qualifier. But -all is the correct, honest statement of intent, and you should aim to get there once you are confident your record is complete.
Account for every other sender
The mistake that breaks SPF on Microsoft 365 is forgetting the things that send mail but do not go through Exchange Online. Common culprits:
- Marketing platforms (Mailchimp, HubSpot, Marketo, Campaign Monitor)
- Transactional email services (SendGrid, Postmark, Amazon SES, Mailgun)
- CRM and helpdesk systems (Salesforce, Zendesk, Freshdesk)
- Invoicing, payroll and HR tools that email on your behalf
- On-premises application servers or multifunction printers that relay mail
Each of these needs its own SPF mechanism. For example, a tenant that also sends through SendGrid and Mailchimp might publish:
v=spf1 include:spf.protection.outlook.com include:sendgrid.net include:servers.mcsv.net -all
Watch the 10-lookup limit
SPF has a hard limit: the evaluating server must perform no more than 10 DNS lookups while expanding your record. Each include, a, mx, ptr and redirect mechanism counts, and includes can nest, so a record that looks like three entries can quietly resolve to twelve. When you exceed ten, SPF returns permerror, which most receivers treat as a fail. The result is a self-inflicted authentication failure that gets worse the day you enforce DMARC.
Microsoft's own include (spf.protection.outlook.com) is well behaved and counts as a small number of lookups, but third-party includes are frequently greedy. Check your total with the SPF checker, which counts lookups for you. If you are over the limit, the proper fix is SPF flattening: replacing bloated includes with the resolved IP ranges and keeping them current as providers change. That is exactly what the hosted SPF product automates, so you never silently break SPF again. If you want to build a clean record from scratch, the SPF generator and the broader tools index will help.
A final SPF note specific to Microsoft 365: you should have only one SPF (v=spf1) TXT record per domain. Two SPF records is a permerror. If the Microsoft setup wizard added one and a previous admin added another, merge them into a single record.
Step 2: Enable DKIM signing with Microsoft's two selectors
This is the step that gets Microsoft 365 from "technically signing" to "aligned and useful". DKIM adds a cryptographic signature to each message that survives most forwarding, which is why DKIM alignment, not SPF, is what carries DMARC through mailing lists and forwarders.
The two CNAME records
Microsoft's DKIM implementation for custom domains uses two selectors, selector1 and selector2, and it expects you to publish two CNAME records in your DNS rather than TXT records containing the public key. For a domain yourcompany.com whose initial tenant domain is yourcompany.onmicrosoft.com, the records are:
selector1._domainkey.yourcompany.com CNAME selector1-yourcompany-com._domainkey.yourcompany.onmicrosoft.com
selector2._domainkey.yourcompany.com CNAME selector2-yourcompany-com._domainkey.yourcompany.onmicrosoft.com
The exact target hostnames are shown to you in the Microsoft 365 Defender portal (Security, then Email and collaboration, Policies and rules, Threat policies, Email authentication settings, DKIM) when you select the domain. Always copy them from the portal rather than guessing, because the tenant identifier in the target can differ from a simple substitution.
Why two selectors? Microsoft uses them to rotate keys without an outage. At any time one selector is the active signing key and the other is the next key being rotated in. Because both CNAMEs point back into Microsoft's infrastructure, Microsoft can publish a new key under the standby selector and switch signing to it without you touching DNS. This is genuinely convenient: you publish the two CNAMEs once and Microsoft handles key rotation for the life of the domain. The cost is that you must publish both CNAMEs, not just one, or rotation will eventually break your signing.
Turning signing on
Publishing the CNAMEs is necessary but not sufficient. After the records have propagated, you must explicitly enable DKIM signing for the domain in the portal (the toggle that reads "Sign messages for this domain with DKIM signatures"). Until you flip that switch, Microsoft keeps signing with the default onmicrosoft.com domain and your custom-domain DKIM stays dormant. If the toggle refuses to enable, it is almost always because one or both CNAMEs are missing, mistyped, or not yet propagated.
Verify the result with the DKIM checker, querying selector1 and selector2 for your domain. A correctly configured domain returns a valid public key for at least the active selector, and inspecting a delivered message header should show d=yourcompany.com rather than d=yourcompany.onmicrosoft.com. That d= value matching your From: domain is the alignment you were missing.
A subtlety with subdomains and parked domains
DKIM in Microsoft 365 is configured per accepted domain. If you send from mail.yourcompany.com or from several brand domains in one tenant, each needs its own pair of selector CNAMEs and its own enablement. Domains you own but never send from should not be left bare: give them a restrictive SPF (v=spf1 -all) and a DMARC record at p=reject so they cannot be abused. The requirements overview covers how the mailbox providers now expect both sending and non-sending domains to be locked down.
Step 3: Publish DMARC at p=none and start reading reports
With aligned SPF and aligned DKIM in place, you are ready to publish DMARC. Resist the urge to jump straight to enforcement. The point of the first DMARC record is not to block anything; it is to turn on reporting so you can see, from real receiver data, every source sending as your domain before you decide what to reject.
Publish a TXT record at _dmarc.yourcompany.com:
v=DMARC1; p=none; rua=mailto:reports@yourcompany.com; fo=1; adkim=s; aspf=s
Breaking that down:
p=nonemeans take no action, only observe and report.rua=is the address that receives the daily aggregate (XML) reports. Point it somewhere you will actually process. Raw XML is unreadable by hand, so feed it into the DMARC report analyzer or use emailed monitoring that parses it for you.fo=1asks receivers to generate a failure report whenever any underlying check fails, which is useful diagnostic detail during rollout.adkim=sandaspf=sset strict alignment. You can start with relaxed (the default) and tighten later, but for a clean Microsoft 365 setup strict is achievable and more secure.
Build and validate the exact string with the DMARC generator, then confirm it is live and syntactically correct with the DMARC checker.
Now leave it. Spend at least two to four weeks reading aggregate reports. You are looking for one thing above all: a list of every IP and provider sending mail that claims to be your domain, and whether each one passes DMARC. Some of those sources will be legitimate systems you forgot about (the printer in the warehouse, a finance app, a legacy server). Each legitimate source must be brought into authentication, by adding it to SPF and, where possible, enabling DKIM for it, before you tighten the policy. Sources that are not yours and are failing are the spoofing you are about to shut down.
Step 4: Move to quarantine, then reject
Once the reports show that all your legitimate mail is passing DMARC (aligned SPF or aligned DKIM), step the policy up. Do it in stages, using the percentage tag to limit blast radius.
First, quarantine a fraction of failing mail:
v=DMARC1; p=quarantine; pct=25; rua=mailto:reports@yourcompany.com; adkim=s; aspf=s
The pct=25 tag tells receivers to apply the quarantine policy to only a quarter of failing messages and treat the rest as p=none. This lets you watch for any legitimate source you missed without sending all of it to spam at once. If reports stay clean for a week or two, raise pct to 50, then 100.
When 100 percent quarantine has run cleanly, move to full enforcement:
v=DMARC1; p=reject; rua=mailto:reports@yourcompany.com; adkim=s; aspf=s
At p=reject, mail that fails DMARC is rejected at the receiving server rather than delivered to a junk folder. This is the policy that actually stops domain spoofing and is what the major mailbox providers expect from bulk senders. Reaching it safely is the entire reason for the staged approach: you never enforce against mail you have not first verified, and the percentage ramp gives you a controlled rollback if something surprising appears.
The conceptual journey from none to reject is covered in more depth in how enforcement works, and the staged monitoring discipline behind it in how to monitor DMARC.
A Microsoft 365 specific warning about inbound
There is a quirk worth knowing. Microsoft 365's inbound filtering has historically not honoured a sender's p=reject by outright rejecting at SMTP time in every configuration; depending on your anti-spam policy settings it may quarantine or junk such mail instead. This affects how Microsoft treats inbound spoof attempts against you, and it is governed by your Defender anti-phishing and spoof intelligence policies, not by your own DMARC record. The takeaway: publishing p=reject protects you everywhere your mail is received, but to make sure inbound spoofs against your own users are handled strictly, also review the spoof intelligence and anti-phishing policy settings in the Defender portal so they act on DMARC failures rather than ignoring them.
Putting it together: a working Microsoft 365 configuration
For a single-domain tenant sending only through Exchange Online plus one marketing provider, a fully enforced configuration looks like this once complete:
SPF (TXT at the root of yourcompany.com):
v=spf1 include:spf.protection.outlook.com include:servers.mcsv.net -all
DKIM (two CNAMEs, signing enabled in the portal):
selector1._domainkey CNAME selector1-yourcompany-com._domainkey.yourcompany.onmicrosoft.com
selector2._domainkey CNAME selector2-yourcompany-com._domainkey.yourcompany.onmicrosoft.com
DMARC (TXT at _dmarc.yourcompany.com):
v=DMARC1; p=reject; rua=mailto:reports@yourcompany.com; adkim=s; aspf=s
That is a domain that authenticates all its own mail and rejects everything pretending to be it.
Going further: MTA-STS and BIMI
DMARC at p=reject is the milestone, but two further records are worth adding on Microsoft 365.
MTA-STS enforces TLS encryption for inbound mail, closing a downgrade attack that DMARC does not address. Microsoft supports MTA-STS for Exchange Online, and you publish a policy file plus a DNS record. The mechanics are in the MTA-STS product overview, and you can validate yours with the MTA-STS checker.
BIMI displays your verified logo next to authenticated mail in supporting clients, including Outlook's evolving support, and it requires p=quarantine or p=reject as a prerequisite, which is one more reason to finish the DMARC journey first. See the BIMI product page and the BIMI checker.
Common Microsoft 365 mistakes and how to avoid them
- Enabling the DKIM toggle before the CNAMEs have propagated. Publish DNS first, wait, then enable. The portal will refuse otherwise.
- Publishing only
selector1and skippingselector2. Both are required; missing the second one breaks Microsoft's key rotation later, not immediately, which makes it hard to diagnose. - Forgetting third-party senders before enforcing. A marketing platform that is not in SPF and cannot DKIM-align will be rejected the moment you reach
p=reject. Find them in your aggregate reports first. - Leaving two SPF records after the setup wizard. Merge them into one.
- Jumping from
p=nonetop=rejectovernight. Usequarantineand thepctramp so any missed source surfaces in a junk folder, not a hard bounce. - Pointing
rua=at a mailbox nobody reads. Aggregate XML is the only ground truth you have during rollout; route it to monitoring that actually parses and alerts on it.
The practical takeaway
Microsoft 365 hands you a short SPF include and an automated DKIM key-rotation scheme, which removes two of the hardest parts of email authentication. The work that remains is discipline rather than difficulty: account for every sender in SPF, publish both DKIM selector CNAMEs and switch signing on for your real domain, then walk DMARC from none through quarantine to reject while reading the reports at each step so you never block your own mail.
Start by running your domain through the DMARC checker, SPF checker and DKIM checker to see exactly where you stand today. If the staged rollout, report-reading and ongoing change alerts are more than you want to own, the done-for-you DMARC service takes a Microsoft 365 domain from p=none to p=reject with no email outage and keeps watching it afterwards. Either way, you now know the order to do it in, which is most of the battle.