DNSSEC and DANE for Exchange Online: turn the mail test green

A mail test such as our email security check often looks like this: IPv6, SPF, DKIM and DMARC are green, and the score stalls well short of 100%. Red: not all domain names are DNSSEC-signed, and the mail-server connection is not or insufficiently secured (STARTTLS and DANE).

That is not a missing checkbox inside the Exchange Online tenant. Outbound DANE has been on for all tenants since 2022. For inbound mail you must sign your own zone first, then move MX off the legacy host mail.protection.outlook.com onto Microsoft’s DNSSEC-signed *.mx.microsoft name, then let Microsoft publish TLSA.

Order is hard. Your own domain must be DNSSEC-signed (DS at the registry, chain valid) before you run Enable-DnssecForVerifiedDomain or change MX. That cmdlet does not sign 365fanatic.com. Without a signed zone, the DNSSEC check still fails, and senders that enforce DNSSEC cannot trust the new MX.

What the mail test actually measures

SPF, DKIM and DMARC prove who may send as your domain. STARTTLS, DNSSEC and DANE are about the path to your mailbox: is the MX authentic, and is the receiving server’s certificate bound in DNS so a man-in-the-middle cannot swap it?

DANE without DNSSEC does not exist. If DNS is unsigned, an attacker can forge MX and TLSA. Exchange Online always offers STARTTLS, but without TLSA records the DANE check stays red.

What fails on mail.protection.outlook.com

A real test against MX 365fanatic-com.mail.protection.outlook.com shows four red subtests. They all belong to Microsoft’s legacy inbound host. You cannot turn cipher suites or SHA-1 off in the tenant admin center. The fix is the MX cutover — after your zone has DNSSEC.

Subtest What it says Why it matters
DNSSEC existence (MX) mail.protection.outlook.com is not DNSSEC-signed. The test does not only check your own zone. It also checks the mail-server domain of the MX host. Without a signature on that SOA, an attacker can forge the DNS answer with the mail-server IP and divert mail or tap TLS. DNSSEC on the apex alone is not enough while MX still points at this unsigned host.
DANE existence No TLSA record on that MX host. DANE (RFC 7672) puts the port-25 TLS certificate in DNS at _25._tcp.. A sender that checks DANE rejects a forged certificate even if a CA issued it. Without TLSA you only have opportunistic STARTTLS. For SMTP only DANE-TA(2) and DANE-EE(3) count; PKIX-TA(0) and PKIX-EE(1) are ignored. Microsoft publishes DANE TLSA on *.mx.microsoft only after Enable-SmtpDaneInbound.
Cipher suites CBC, RSA key-exchange, AES-128 — NCSC “insufficient” or “phase out”. A TLS connection test measures against NCSC-NL TLS 2025-05 (par. 3.3.2–3.3.5). CBC and classic RSA key-exchange are too weak or obsolete; a client can negotiate down. This is the TLS profile of Microsoft’s legacy inbound cluster. Exchange Online has no “turn CBC off” switch. Cipher score stays Microsoft’s responsibility, not something you set in Cloudflare.
Hash function for key exchange SHA-1 on the same MX (TLS 1.2 signatures). On TLS 1.2 the server signs the key-exchange. SHA-1 is “insufficient” per NCSC (RFC 9155); good is SHA-256/384/512. No tenant setting. While MX stays on mail.protection.outlook.com, this subtest stays red.

DNSSEC existence and DANE existence go green after MX moves to a signed Microsoft host and DANE is enabled. Cipher suites and SHA-1 live in Microsoft’s TLS stack. They can still be red on the new host until Microsoft tightens inbound TLS.

Two layers, not one switch

  1. DNSSEC on your own zone (Cloudflare / registrar). Apex, www, autodiscover and the MX lookup must sit in a signed zone with DS at the TLD. This is “not all domain names signed”.
  2. Inbound SMTP DANE in Exchange Online. Microsoft does not publish TLSA on mail.protection.outlook.com. You switch MX to *.mx.microsoft (DNSSEC-signed) and then enable DANE. Microsoft writes the TLSA records; you do not create them.

Outbound DANE (mail from Exchange Online to a recipient that has DANE) is already on. You do not configure that.

Step 1 — DNSSEC on the domain (Cloudflare)

Do not touch Exchange Online until this is green.

  1. Cloudflare → the domain → DNS → Settings → Enable DNSSEC.
  2. If the registrar is elsewhere (SIDN, TransIP, …), copy the DS record Cloudflare shows into the registrar. Without DS at the TLD the zone is “signed but insecure”, and the DNSSEC check stays red.
  3. If Cloudflare is the registrar, one click is enough; the DS goes to the registry automatically.
  4. Wait until the chain is live (minutes, sometimes up to 24 hours). Check with the Verisign DNSSEC Debugger or dig +dnssec MX your-domain.nl.

Do not turn DNSSEC off “to test” once the DS is at the registry: resolvers that enforce DNSSEC will then refuse the whole zone.

Step 2 — Exchange Online: DNSSEC MX

Do not start until step 1 is green. Further prerequisites: the domain is an Accepted domain with status Healthy, MX currently points to …mail.protection.outlook.com, Exchange Online PowerShell in PowerShell 7 (not ISE). Microsoft’s steps assume a single MX.

If you use MTA-STS: set the policy to testing, bump the policy id, wait until max_age has expired, then change the mx: row to the new host. Only then set enforce again.

Lower the TTL of the current MX (minimum 30 seconds). Wait until the old TTL has expired. Then:

PowerShell
Connect-ExchangeOnline
Enable-DnssecForVerifiedDomain -DomainName "contoso.nl"

The output contains DnssecMxValue, for example contoso-nl.o-v1.mx.microsoft. That is the new MX host. You do not create TLSA; you do create this MX record:

  1. New MX: value = DnssecMxValue, priority 20, TTL as low as possible (≥ 30 s).
  2. Test mail flow: Inbound SMTP Email in the Remote Connectivity Analyzer. Under Test Steps the exchanger must end in mx.microsoft.
  3. Old MX (mail.protection.outlook.com) to priority 30; new MX to priority 0.
  4. Wait until mail is arriving. Delete the old MX. Set the new MX TTL to 3600.

Partners or connectors that hard-code tenant.mail.protection.outlook.com must follow the new host (or keep that name as Microsoft’s smarthost — not as your public MX). Third-party gateways (Proofpoint, Mimecast, …) must support DNSSEC/DANE themselves, or the chain stops at the gateway.

Step 3 — Inbound DANE (TLSA)

Only once the DNSSEC MX is live:

PowerShell
Enable-SmtpDaneInbound -DomainName "contoso.nl"

Exchange Online publishes TLSA at _25._tcp. (15–30 minutes). Microsoft publishes several TLSA records; it is normal for one to fail at a validator, as long as at least one succeeds.

PowerShell
Get-DnssecStatusForVerifiedDomain -DomainName "contoso.nl"
Get-SmtpDaneInboundStatus -DomainName "contoso.nl"

Step 4 — Test

  1. Microsoft DNSSEC and DANE Validation — first DNSSEC only, then DANE including DNSSEC.
  2. Our email security check — after the DNS cache expires (sometimes hours) DNSSEC and DANE should go green. With SPF, DKIM, DMARC and IPv6 already fine, the score then reaches the top. Cipher suites and SHA-1 are not DNS settings; a TLS connection test can still show them Microsoft-red.

Test the mail domain (the name after @), not only www. A website test is not the yardstick here.

What not to do

  • Publish a TLSA record on your zone for Outlook yourself. It belongs on Microsoft’s MX host, and Microsoft writes it.
  • Leave old and new MX both at priority 0 “to be safe”. Senders then pick the unsigned host at random and DANE fails intermittently.
  • Turn on inbound DANE on tenant.onmicrosoft.com. Microsoft does not support that.
  • Force this in a five-minute change window. MX cutover follows TTLs; plan it, send a test message, then clean up.
  • Run Enable-DnssecForVerifiedDomain while your zone still has no DS at the registry.

Roll back

PowerShell
Disable-SmtpDaneInbound -DomainName "contoso.nl"
Disable-DnssecForVerifiedDomain -DomainName "contoso.nl"

Then point MX back to contoso-nl.mail.protection.outlook.com (or whatever the admin center shows). Leave DNSSEC on in Cloudflare: that is your zone, not Microsoft’s MX.

In short

The mail test is not marking a missing Microsoft checkbox. It is marking an unsigned zone and an MX without DANE. Sign the domain at Cloudflare (including DS at the registrar) first. Move MX to *.mx.microsoft with Enable-DnssecForVerifiedDomain. Then Enable-SmtpDaneInbound. Recheck with the Microsoft analyzer and our email security check. SPF/DKIM/DMARC stay as they are; this is the transport layer on top.

Sources: Microsoft Learn, How SMTP DANE works; cmdlets Enable-DnssecForVerifiedDomain and Enable-SmtpDaneInbound. Test: 365Fanatic email security check.

Frequent errors and how to fix them

These are the messages people type into search when the module will not start. The exact wording is here so this page can be found.

The term 'Connect-ExchangeOnline' is not recognized
Module not installed, or the wrong host. Install-Module ExchangeOnlineManagement, then open a new window.
A window handle must be configured / MsalClientException
MSAL/WAM handler bug: no window for sign-in. As administrator: winget install --id Microsoft.PowerShell --source winget, then pwsh. ISE still hosts 5.1; the Exchange module does run there. Staying in ISE: Connect-ExchangeOnline -DisableWAM. Headless scripts: certificate or managed identity. Full explanation.
Error Acquiring Token: System.NullReferenceException / 0x80070520
WAM sign-in (module 3.7.0+) failed. NullReferenceException: another module in the same window (usually Microsoft Graph) loaded a different MSAL version; new window, Connect-ExchangeOnline first, or -DisableWAM. 0x80070520 "A specified logon session does not exist": PowerShell runs as another account or in Task Scheduler; start as yourself, or use a certificate. Full explanation.
WinRM cannot process the request / CreateExoPSSession
Legacy V1/V2 remoting. Use module V3+ and Connect-ExchangeOnline (no separate WinRM session).
AADSTS50076 / MFA required
Interactive: complete MFA. For scripts: certificate (app-only), not a user password.
Unauthorized / Access Denied
The account or app registration has no Exchange role (for example Exchange Administrator). App-only: Exchange.ManageAsApp plus that role.
Could not create SSL/TLS secure channel
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 — or use PowerShell 7.
Fail to create a runspace / connecting to outlook.office365.com
Legacy remote PowerShell. Update to ExchangeOnlineManagement V3; REST is the default. Disconnect-ExchangeOnline -Confirm:$false between jobs.
The term 'Get-Mailbox' is not recognized
You are not connected, or the REST session expired. Connect-ExchangeOnline again; do not mix with a leftover MSOnline session.

Questions about this, or need help setting it up? We are happy to think along.

Message on LinkedIn →