Skip to content

SPF, DKIM and DMARC in Microsoft 365, by DNS host

For a domain that uses Microsoft 365, mail authentication is set up with three DNS records: a TXT record containing include:spf.protection.outlook.com for SPF, two CNAME records named selector1._domainkey and selector2._domainkey for DKIM, and a TXT record named _dmarc for DMARC. Microsoft 365 decides what the records say; your domain's DNS hosting provider decides where and how they are written.

This article walks through the three records in order and shows how to do the same job in Azure DNS, Cloudflare and a registrar panel such as Natro. For the concepts, see the SPF, DKIM and DMARC articles.

Where is my DNS, and how do I find out?

You change DNS records wherever your domain's name servers (NS) are operated. That is not always the company you bought the domain from. To find out:

nslookup -type=NS ornek.com.tr
Name server formatDNS provider
Ending in azure-dns.com/.net/.org/.info, such as ns1-01.azure-dns.comAzure DNS
<name>.ns.cloudflare.comCloudflare
<name>.natrohost.comNatro

If the name servers are spread across more than one provider (for example during a migration), a change made at only one of them is incomplete; first establish which one is authoritative.

Step 1: How do you add the SPF record?

Publish this TXT record on the domain itself (@):

ornek.com.tr.  IN  TXT  "v=spf1 include:spf.protection.outlook.com -all"

If any other system sends mail (CRM, newsletter service, printer), add its include: or ip4: value to the same record. If the domain already has a record starting with v=spf1, do not add a second one next to it; edit the existing record. Two SPF records are invalid and receivers ignore SPF.

Step 2: How do you enable DKIM in Microsoft 365?

Until you enable DKIM, Microsoft 365 does not sign mail from your custom domain with your own domain. Some tenants may show an onmicrosoft.com signature, but it is not aligned with your From domain and does not help DMARC. For your own domain:

  1. Get the CNAME values. In the Microsoft Defender portal, go to Email & collaboration › Policies & rules › Threat policies › Email authentication settings › DKIM (direct link: https://security.microsoft.com/authentication?viewid=DKIM) and select your domain. The portal shows the two CNAME targets you need to publish. They are Microsoft-managed addresses specific to your tenant and domain; different formats, ending in onmicrosoft.com or dkim.mail.microsoft, can appear. Do not guess; copy what the portal shows.
  2. Add the two CNAME records to DNS:
selector1._domainkey.ornek.com.tr.  IN  CNAME  <Selector1CNAME-value>
selector2._domainkey.ornek.com.tr.  IN  CNAME  <Selector2CNAME-value>
  1. Enable DKIM once the records are visible from outside. On the same DKIM page, turn on signing for the domain.

The same can be done with Exchange Online PowerShell (the commands are run by your tenant's administrator). If the domain has no DKIM configuration yet, create it disabled first, then read the CNAME values:

New-DkimSigningConfig -DomainName ornek.com.tr -KeySize 2048 -Enabled $false
Get-DkimSigningConfig -Identity ornek.com.tr | Format-List Selector1CNAME,Selector2CNAME

After the CNAME records are published:

Set-DkimSigningConfig -Identity ornek.com.tr -Enabled $true

Step 3: How do you add the DMARC record?

DMARC always starts in monitoring mode:

_dmarc.ornek.com.tr.  IN  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@ornek.com.tr"

When the reports arriving at rua show Microsoft 365 and your other legitimate senders passing SPF or DKIM with alignment, raise the policy to p=quarantine, and after a few clean weeks to p=reject. Do not add pct=; if you do, the policy applies to only part of the mail.

How do you add the records in Azure DNS?

Portal: DNS zones › ornek.com.tr › Recordsets › + Add. Enter Name, Type and Value for each record; the apex record's name is @. If a record set with the same name and type already exists, do not create a new one; open that set and add or edit the value.

Azure CLI (Cloud Shell or after az login; identical in bash and PowerShell). <resource-group> is the resource group that holds the DNS zone; it is shown on the zone's Overview page:

az network dns record-set txt add-record --resource-group "<resource-group>" --zone-name "ornek.com.tr" --record-set-name "@" --value "v=spf1 include:spf.protection.outlook.com -all"
az network dns record-set cname set-record --resource-group "<resource-group>" --zone-name "ornek.com.tr" --record-set-name "selector1._domainkey" --cname "<Selector1CNAME-value>"
az network dns record-set cname set-record --resource-group "<resource-group>" --zone-name "ornek.com.tr" --record-set-name "selector2._domainkey" --cname "<Selector2CNAME-value>"
az network dns record-set txt add-record --resource-group "<resource-group>" --zone-name "ornek.com.tr" --record-set-name "_dmarc" --value "v=DMARC1; p=none; rua=mailto:dmarc@ornek.com.tr"

If you are replacing an existing SPF record, look at the set first, remove the old value, then add the new one:

az network dns record-set txt show --resource-group "<resource-group>" --zone-name "ornek.com.tr" --name "@"
az network dns record-set txt remove-record --resource-group "<resource-group>" --zone-name "ornek.com.tr" --record-set-name "@" --value "<current-spf-record>" --keep-empty-record-set

Do not run the commands before filling in the <...> placeholders.

How do you add the records in Cloudflare?

Cloudflare dashboard › ornek.com.tr › DNS › Records › Add record:

TypeNameContent / Target
TXT@v=spf1 include:spf.protection.outlook.com -all
CNAMEselector1._domainkey<Selector1CNAME-value>
CNAMEselector2._domainkey<Selector2CNAME-value>
TXT_dmarcv=DMARC1; p=none; rua=mailto:dmarc@ornek.com.tr

For the CNAME records, Proxy status must be DNS only (grey cloud). If the proxy stays on, the query returns Cloudflare IP addresses instead of the CNAME target and DKIM verification fails; new records may have the proxy turned on by default.

How do you add them in Natro or another registrar panel?

Natro customer panel › ornek.com.tr › DNS management. Other registrars follow a similar path: select the domain and open DNS management or DNS records. The Type, Name and Value triple from the table above is the same in every panel. Watch out for:

  • The apex record: enter @ as the name; some panels ask you to leave it empty.
  • Doubled names: if the panel appends the domain to the name itself, enter only _dmarc. Entering _dmarc.ornek.com.tr may create the record as _dmarc.ornek.com.tr.ornek.com.tr.
  • Quotes: some panels add quotes to TXT values themselves; enter the value without quotes and check the result with a query.

How do I verify the setup?

nslookup -type=TXT ornek.com.tr
nslookup -type=CNAME selector1._domainkey.ornek.com.tr
nslookup -type=TXT _dmarc.ornek.com.tr

Then send a message from your domain to an outside mailbox and, on the receiving side, check that the Authentication-Results header shows spf=pass, dkim=pass (header.d=ornek.com.tr) and dmarc=pass.

What comes after the three records?

SPF, DKIM and DMARC tell spoofed senders apart, but they do not make encrypted delivery mandatory. Two standards do: MTA-STS (RFC 8461) asks servers sending you mail to connect to your MX only over validated TLS; DANE (RFC 7672) binds the MX server's certificate to a DNSSEC-signed TLSA record. Denetta assesses these separately (e.g. MAIL-014 for MTA-STS, MAIL-029 for DANE).

What does Denetta check in this setup?

Denetta's Domain and Email Security module recognises the mail provider from the MX records and the DNS hosting provider from the name servers. In a finding's remediation text, the record content follows Microsoft 365 (e.g. include:spf.protection.outlook.com, the selector1/selector2 CNAMEs) and the format follows the DNS provider (Azure Portal steps and an az command, or the Cloudflare or Natro panel path). Unrecognised or mixed name servers get the generic text. Relevant rule codes include MAIL-001 (no SPF), MAIL-010 (no DKIM), MAIL-006 (no DMARC) and MAIL-007 (p=none).

Remediation text is only displayed; Denetta never changes a DNS record and never runs a command. You can see your status with the domain security check: it reads only DNS records and produces a pre-check score from 21 rules; the full module has 31 rules.

Frequently asked questions

Isn't DKIM on by default in Microsoft 365?

Until you enable DKIM, Microsoft 365 does not sign mail from your custom domain with your own domain. Some tenants may show an onmicrosoft.com signature, but it is not aligned with your From domain and does not help DMARC. You need to enable DKIM for your own domain.

Where do I get the DKIM CNAME values?

From the DKIM tab on the Email authentication settings page of the Microsoft Defender portal (https://security.microsoft.com/authentication?viewid=DKIM), or from the Selector1CNAME and Selector2CNAME fields of Get-DkimSigningConfig in Exchange Online PowerShell. The values are specific to your tenant and domain; copy them, do not guess.

My DNS is not in Microsoft 365 but somewhere else. Who adds the records?

The records are added wherever your domain's name servers (NS) are operated: Azure DNS, Cloudflare, your registrar's panel or your own DNS server. The mail provider decides what the record says; the DNS provider decides where and how it is written.

I added the records. When do they take effect?

Between a few minutes and a few hours, depending on the record's TTL and caches. You can enable DKIM in the Defender portal once the CNAME records are visible from outside.

How is your domain doing?

Measure your SPF, DKIM, DMARC and DNSSEC records with DNS queries only, without connecting to your servers.

Check your domain

Let’s review your infrastructure together.

Let us show Denetta in a meeting with your own scenario, or request your free first report from a FortiGate backup.