Email authentication

Microsoft 365 setup checker

Check a domain’s Microsoft 365 SPF include and both DKIM selector CNAMEs, mistake by mistake.

Free, no accountLive check

Try

Result

The verdict appears here once you press Check Microsoft 365 records.

What this is

This Microsoft 365 setup checker reads the two DKIM selector hostnames every tenant shares, confirms each one is a CNAME rather than a TXT record, and compares the part of its target that can be computed from your domain - then checks the SPF include for whichever of Microsoft’s three clouds you are on.

Microsoft 365 publishes the same two DKIM hostnames for every organisation, selector1._domainkey and selector2._domainkey, and both have to be CNAME records. Their targets are only half yours: the selector and your domain with its periods turned into dashes, then a tenant prefix and, in the newer format, a partition character that Microsoft assigns and you cannot choose.

Two target formats are in circulation. Custom domains added since May 2025 get a target ending in "-v1.dkim.mail.microsoft"; existing custom domains and initial domains keep one ending in onmicrosoft.com. Microsoft says the two cannot coexist for the same selector, so a domain is on one or the other and seeing either is not a fault.

How to read the result

Each selector row says which of the two documented formats its target matched, or which named mistake it ran into instead: a TXT record where the CNAME belongs, a hostname carrying the domain twice because the DNS editor appended the zone to a name that already ended in it, or a target with the periods still in the domain where dashes belong.

Only the computable part of the target is compared exactly, and the page says so rather than implying more. A target that starts with the right selector and the right dashed domain, and ends somewhere this page has not seen before, is reported as matching the shape - the Defender portal is the only place the real value for a tenant is shown.

This checker only covers Microsoft 365’s own fixed SPF include and the two DKIM selectors. For how SPF, DKIM and DMARC fit together, what order to fix them in, and what to do once one fails, see our guide How SPF, DKIM and DMARC work together, and what to do when one fails.

Common mistakes

What goes wrong most often, and how to tell.

  • Publishing selector1 and leaving selector2 for laterMicrosoft requires both records. With one of them, signing enables successfully and messages are signed, so the setup looks finished - and then the first key rotation fails because there is no second selector to rotate into. The gap usually surfaces long after anyone remembers making it.
  • Creating the selector as a TXT record holding a keyEvery other DKIM setup in the world is a TXT record with a public key in it, so this is the natural thing to do and it is not supported here. The CNAME exists precisely so Microsoft can replace the key behind it without anyone editing DNS again.
  • Letting the DNS editor append the domain twiceMost editors add the zone to whatever goes in the host field, so pasting the fully qualified hostname produces selector1._domainkey.contoso.com.contoso.com. The record exists, resolves and is never consulted by anything, which is the most time-consuming way for this to fail.
  • Leaving the periods in the domain part of the targetMicrosoft replaces every period in the custom domain with a dash, so contoso.com becomes contoso-com and marketing.contoso.com becomes marketing-contoso-com. Copying the target by hand and keeping the periods produces a name that looks almost right and resolves to nothing.
  • Setting the selector TTL very low to make a change arrive soonerA very low TTL is on Microsoft’s own list of things that stop DKIM working, and it is also invisible from outside: what a resolver returns is whatever is left of a cached answer, not the number in your zone. It is worth checking in the zone itself rather than with a lookup.

Questions

What people ask about this tool.

  • Because rotation alternates between them. Microsoft requires both CNAME records: with only selector1 published, signing enables and works, and then key rotation fails later - which is why a missing selector2 almost always turns up months after the setup appeared to be complete.
  • No. A TXT record at selector1._domainkey or selector2._domainkey is not supported for Microsoft 365 and appears on Microsoft’s own list of mistakes that prevent DKIM working. The CNAME is what lets Microsoft rotate the key behind it without you editing DNS again.
  • No. Microsoft documents spf.protection.office365.us for GCC High and DoD, and spf.protection.partner.outlook.cn for Office 365 operated by 21Vianet. This page recognises all three and names the cloud it found, rather than failing the two that are not the commercial one.
  • No. Correct CNAME records make signing possible; switching it on happens in the Defender portal and leaves no trace in DNS. Microsoft also says the CNAME values printed in its article are illustrations, so the portal is the only place the real targets for your tenant appear.

Sources

Every fixed value here comes from the provider’s own documentation. These pages change, so each says the day it was last read.

Use it from the API

The same check, as one request.

Request
curl -X POST https://resellerhq.com/api/tools/microsoft-365-setup-checker \
  -H "Content-Type: application/json" \
  -d '{"domain":"tenant.example"}'
Response
{
  "tool": "microsoft-365-setup-checker",
  "input": {
    "domain": "tenant.example"
  },
  "result": {
    "verdict": {
      "tone": "success",
      "headline": "tenant.example matches what Microsoft documents",
      "summary": "The SPF include is there and both selector hostnames are CNAMEs in one of the two documented formats."
    },
    "findings": [
      {
        "id": "tenant-prefix-unverifiable",
        "severity": "info",
        "title": "The tenant part of the target cannot be checked from here",
        "detail": "Only \"selector1-tenant-example._domainkey.\" is computable from the domain, and that is what was compared exactly. The tenant prefix after it, and the partition character before \"-v1\" in the new format, come from Microsoft's own routing and are not configurable, so nothing outside the tenant can confirm them."
      },
      {
        "id": "dkim-key-type-recognised",
        "severity": "info",
        "title": "DKIM: 2048-bit RSA key",
        "detail": "The modulus decoded from \"p=\" is 2048 bits, read directly from the DER-encoded key rather than estimated from its length."
      },
      {
        "id": "mail-routed-to-microsoft-365",
        "severity": "pass",
        "title": "Mail for this domain is delivered by Microsoft 365",
        "detail": "0 tenant-example.mail.protection.outlook.com - a host under mail.protection.outlook.com, so the tenant that owns the name in front of it is the one the records below belong to."
      },
      {
        "id": "spf-outlook-include-present",
        "severity": "pass",
        "title": "SPF authorises Microsoft to send",
        "detail": "The chain at tenant.example reaches include:spf.protection.outlook.com, which is the include Microsoft documents for Microsoft 365 and GCC. All three of its clouds use a different name, and this is the right one for that cloud rather than the only one that counts."
      },
      {
        "id": "selector1-cname-found",
        "severity": "pass",
        "title": "selector1 is a CNAME in the new format",
        "detail": "selector1._domainkey.tenant.example is a CNAME to selector1-tenant-example._domainkey.tenant.a-v1.dkim.mail.microsoft, which starts with the selector1-tenant-example._domainkey. Microsoft computes from the domain and ends in the \"-v1.dkim.mail.microsoft\" form introduced in May 2025 for new custom domains."
      },
      {
        "id": "selector2-cname-found",
        "severity": "pass",
        "title": "selector2 is a CNAME in the new format",
        "detail": "selector2._domainkey.tenant.example is a CNAME to selector2-tenant-example._domainkey.tenant.a-v1.dkim.mail.microsoft, which starts with the selector2-tenant-example._domainkey. Microsoft computes from the domain and ends in the \"-v1.dkim.mail.microsoft\" form introduced in May 2025 for new custom domains."
      },
      {
        "id": "spf-spf-record-found",
        "severity": "pass",
        "title": "SPF: SPF record found",
        "detail": "tenant.example publishes \"v=spf1 include:spf.protection.outlook.com -all\", using 1 of the 10 DNS lookups RFC 7208 §4.6.4 allows."
      },
      {
        "id": "spf-hardfail-all",
        "severity": "pass",
        "title": "SPF: \"-all\" hard-fails unlisted senders",
        "detail": "Anything not explicitly listed in this record fails SPF outright, which is what a finished record should say once every real sending server is accounted for."
      },
      {
        "id": "dmarc-dmarc-record-found",
        "severity": "pass",
        "title": "DMARC: DMARC record found",
        "detail": "_dmarc.tenant.example publishes \"v=DMARC1; p=reject; rua=mailto:[email protected]\". A receiver that honours this rejects failing mail outright."
      }
    ],
    "parts": [
      {
        "kind": "table",
        "title": "What Microsoft documents, against what this domain publishes",
        "columns": [
          "Record",
          "What Microsoft documents",
          "Published at tenant.example"
        ],
        "rows": [
          [
            "MX",
            "<tenant>.mail.protection.outlook.com",
            "0 tenant-example.mail.protection.outlook.com"
          ],
          [
            "SPF include",
            "spf.protection.outlook.com",
            "spf.protection.outlook.com"
          ],
          [
            "selector1._domainkey.tenant.example",
            "CNAME to selector1-tenant-example._domainkey.…",
            "CNAME, new format"
          ],
          [
            "selector2._domainkey.tenant.example",
            "CNAME to selector2-tenant-example._domainkey.…",
            "CNAME, new format"
          ]
        ],
        "mono": [
          1,
          2
        ],
        "proseColumns": [
          2
        ],
        "note": "Both selector hostnames are the same for every Microsoft 365 organisation; only the target differs."
      },
      {
        "kind": "text",
        "title": "The two target shapes Microsoft documents",
        "body": "New custom domains, since May 2025:\nselector1-tenant-example._domainkey.<tenant>.<partition>-v1.dkim.mail.microsoft\n\nExisting custom domains and initial domains:\nselector1-tenant-example._domainkey.<tenant>.onmicrosoft.com\n\nThe old and new formats cannot coexist for the same selector, so a domain has one or the other. Microsoft says the values in its own article are illustrations: the real targets for a tenant come from the Defender portal or Exchange Online PowerShell."
      }
    ],
    "lookups": [
      {
        "label": "MX for tenant.example",
        "value": "Cloudflare: 1 record"
      },
      {
        "label": "TXT for tenant.example",
        "value": "Cloudflare: 1 record"
      },
      {
        "label": "TXT for spf.protection.outlook.com",
        "value": "Cloudflare: 1 record"
      },
      {
        "label": "CNAME for selector1._domainkey.tenant.example",
        "value": "selector1-tenant-example._domainkey.tenant.a-v1.dkim.mail.microsoft"
      },
      {
        "label": "CNAME for selector2._domainkey.tenant.example",
        "value": "selector2-tenant-example._domainkey.tenant.a-v1.dkim.mail.microsoft"
      },
      {
        "label": "TXT for selector1._domainkey.tenant.example",
        "value": "Cloudflare: 1 record"
      },
      {
        "label": "TXT for _dmarc.tenant.example",
        "value": "Cloudflare: 1 record"
      }
    ],
    "limits": [
      "Nothing here can confirm DKIM signing is switched on. That lives in the Defender portal, and Microsoft treats enabling it as a separate step from publishing the two CNAME records, so both records can be perfect while no message is signed.",
      "Only the selector and the dashed domain at the front of each target are computable from the domain. The tenant prefix, and the partition character in the new format, are set by Microsoft and cannot be verified from outside the tenant.",
      "A trailing dot and a TTL set too low are both on Microsoft’s own list of mistakes, and neither is visible from out here: a resolver normalises the dot away, and the TTL that comes back is whatever is left of a cached answer rather than the value in your zone.",
      "The MX row recognises the commercial host shape only, so a GCC High, DoD or 21Vianet tenant reads as routed elsewhere even when its records are exactly right."
    ]
  }
}

This example uses a name RFC 2606 reserves for documentation, ending in .example, .test, .invalid or .localhost. None of them is a real domain, and nobody can register one.

Resell mailbox licences for the domains you just checked, under your own brand.

Get started

Company names and logos are trademarks of their owners, shown only to identify each service.