DNSVerdictAll toolsGuidesHow it works

Set up SPF, DKIM and DMARC for Microsoft 365

Published · Updated

For a custom domain on Microsoft 365, publish an MX record whose value you copy from the Microsoft 365 admin center, an SPF TXT record v=spf1 include:spf.protection.outlook.com -all, two DKIM CNAME records at selector1._domainkey and selector2._domainkey whose targets are specific to your tenant, and a DMARC TXT record at _dmarc starting with p=none. The MX value and the DKIM targets cannot be guessed: read them in the admin center or the Defender portal, or with Get-DkimSigningConfig. Then switch DKIM signing on, and tighten DMARC step by step.

Which cloud are you in?

The SPF include depends on the Microsoft 365 environment, according to Microsoft’s SPF article:

EnvironmentSPF record for a Microsoft-only domain
Microsoft 365 worldwide and GCCv=spf1 include:spf.protection.outlook.com -all
GCC High and DoDv=spf1 include:spf.protection.office365.us -all
Operated by 21Vianetv=spf1 include:spf.protection.partner.outlook.cn -all

The rest of this guide uses the worldwide value. Substitute your environment’s include where it appears.

Step 1: MX record

Add users and mailboxes first. Microsoft warns that after you change the MX record, all new mail for the domain goes to Microsoft 365, while existing mail stays at the old host unless you migrate it.

At your DNS host, the manual path in Microsoft’s documentation is:

FieldValue
TypeMX
Host@
Points tothe value shown on the Add DNS records page in the admin center
Prioritythe highest available, typically 0
TTL3600

Microsoft says to copy the MX value from the admin center rather than construct it, because it is per tenant. If MX records for a previous provider exist, either delete them or give them a lower priority (a higher number) than Microsoft’s record. Microsoft also notes that Exchange Online supports only TTL values below 6 hours (21,600 seconds). In the admin center, the records are under Settings > Domains, your domain, DNS records. Check the result with the MX lookup.

Step 2: SPF record

Microsoft 365 has no portal or cmdlet for editing SPF; you create the TXT record at your DNS host.

@   TXT   "v=spf1 include:spf.protection.outlook.com -all"

If an SPF record already exists, do not create a second one. Microsoft says to add its include to the existing record, so that a single record covers the old provider and Microsoft 365. Two v=spf1 records cause permerror.

Combining with other senders. On-premises servers go in as ip4: or ip6:; other services as include:. Microsoft’s article shows this pattern for a domain with an on-premises server (the address here is a documentation placeholder):

@   TXT   "v=spf1 ip4:192.0.2.10 include:spf.protection.outlook.com -all"

Microsoft recommends a subdomain (for example marketing.example.com) for bulk services you do not control. Each subdomain that sends needs its own SPF record, and each gets its own 10-lookup budget.

The 10-lookup limit. Each include:, a, mx, exists and redirect counts as one lookup, and nested includes add more; ip4: and ip6: do not count. Going over produces permerror and may produce a bounce. Microsoft’s article warns against flattening spf.protection.outlook.com into IP addresses, because its addresses change frequently. See SPF has too many DNS lookups for the full treatment and verify with the SPF checker.

-all versus ~all. Microsoft recommends -all because DKIM and DMARC are also in place. Its note: DMARC treats both as SPF failures, but the DMARC policy is effectively ignored for SPF ~all failures if the message has no DKIM signature. If you are still discovering senders, ~all is the safer interim choice; move to -all when your DMARC reports are clean. Use ?all only for testing.

Step 3: DKIM

Without configuration, Microsoft signs with your *.onmicrosoft.com domain, which does not align with your own From domain. For a custom domain you publish two CNAME records. Microsoft generates two key pairs and the CNAMEs point at the public keys. The selectors are named selector1 and selector2.

Get the targets. The CNAME targets have the form selector1-<your-domain-with-dashes>._domainkey.<tenant>.<partition>-v1.dkim.mail.microsoft, and Microsoft states that the examples in its article are for illustration only. Read your real values in the Defender portal:

  1. Go to https://security.microsoft.com/authentication and open the DKIM tab (Email & collaboration > Policies & rules > Threat policies > Email authentication settings).
  2. Select your domain. Per Microsoft’s procedure, toggling signing on before the records exist produces an error and sets the status to CnameMissing; the domain flyout then shows the values under Publish CNAMEs.

Or in Exchange Online PowerShell:

Get-DkimSigningConfig -Identity example.com | Format-List Name,Enabled,Status,Selector1CNAME,Selector2CNAME

Publish the records:

selector1._domainkey   CNAME   <Selector1CNAME value>
selector2._domainkey   CNAME   <Selector2CNAME value>

Wait, then enable. Microsoft says detection takes a few minutes or possibly longer. After that, open the domain flyout and turn on Sign messages for this domain with DKIM signatures, or run Set-DkimSigningConfig -Identity example.com -Enabled $true. If the CNAMEs are not detected, you get an error that repeats the expected values; check for typos in dashes, periods and underscores. A healthy domain shows Enabled: True and Status: Valid, and the DKIM-Signature header of outbound mail shows d=example.com with s=selector1-example-com or the selector 2 equivalent.

Key size. Per Microsoft’s article, the KeySize parameter defaults to 1024; 2048 is available through New-DkimSigningConfig -KeySize 2048 or when rotating: Rotate-DkimSigningConfig -Identity example.com -KeySize 2048. A rotation is not immediate: the new key starts signing after four days (96 hours).

Step 4: DMARC

Microsoft requires SPF and DKIM first, and DKIM must sign with the custom domain so the signing domain aligns with the From domain. There is no admin-center setting for custom domains; create the record at your DNS host. Start in monitoring mode:

_dmarc   TXT   "v=DMARC1; p=none; pct=100; rua=mailto:[email protected]"

Microsoft recommends a gradual rollout: p=none, then p=quarantine, then p=reject, with pct stepping through 10, 25, 50, 75 and 100 if you want to limit exposure. Start with a subdomain of low volume if you have one, and leave the parent domain for last. Subdomains inherit the parent record unless they publish their own.

Trade-offs specific to reject and quarantine: Microsoft notes that outbound mail from your domain that fails DMARC at the destination is routed through the high-risk delivery pool when the policy is p=reject or p=quarantine, with no override. And forwarded mail and mailing lists often fail SPF and break DKIM, so some false positives are expected. Use a dedicated mailbox or group for rua reports. Microsoft 365 does not send forensic (ruf) reports, so do not rely on them. If a service passes SPF and DKIM yet DMARC fails, read DMARC fails even though SPF and DKIM pass.

If you own a domain that never sends mail, Microsoft’s parked-domain values are v=spf1 -all and v=DMARC1; p=reject;.

Step 5: Verify

  1. MX lookup: the Microsoft host only, no older provider at lower numbers.
  2. SPF checker: one record, correct include for your cloud, lookups at or under 10.
  3. DMARC checker: one record at _dmarc, rua present.
  4. Send a message to an outside mailbox and paste its headers into the email header analyzer. spf=pass, dkim=pass header.d=example.com and dmarc=pass is the target.

All records at a glance

HostTypeValue
@MXcopy from the admin center, priority 0
@TXTv=spf1 include:spf.protection.outlook.com -all
selector1._domainkeyCNAMESelector1CNAME from Defender portal or PowerShell
selector2._domainkeyCNAMESelector2CNAME from Defender portal or PowerShell
_dmarcTXTv=DMARC1; p=none; pct=100; rua=mailto:[email protected]

Common mistakes

FAQ

Do I need DKIM if SPF passes? Yes. DMARC needs one aligned pass, and forwarding breaks SPF. Microsoft’s default onmicrosoft.com signature does not align with your custom From domain.

Why does Microsoft recommend -all while some guides say ~all? Microsoft’s reasoning is that DMARC and DKIM handle the enforcement. If you have not yet identified every sender, ~all limits the damage of a missed one.

Can I manage these records inside Microsoft 365? For custom domains, not SPF or DMARC: Microsoft says there are no portals or cmdlets for them. The admin center can add its standard DNS records automatically only if your registrar supports Domain Connect; otherwise you add them manually.

Sources

Tools used

SPF Record CheckerDMARC Record CheckerMX LookupEmail Header AnalyzerEmail Provider Setup Check