A Microsoft 365 DKIM CNAME target has two documented formats: read it per domain, never build it
Microsoft documents two DKIM CNAME target formats for Microsoft 365 custom domains, one ending in onmicrosoft.com and one in dkim.mail.microsoft. The page splits them by new versus existing custom domain and never mentions tenant age. Read each domain's values with Get-DkimSigningConfig.
A Microsoft 365 DKIM CNAME target comes in two documented shapes. One ends in onmicrosoft.com, the other in dkim.mail.microsoft. Microsoft's own page assigns them to different kinds of domain, and a record built by copying the pattern from somewhere else can leave a custom domain stuck at CnameMissing.
Last verified: 2026-09-15.
What Microsoft documents
The reference is Set up DKIM to sign mail from your cloud domain, read in full on 2026-09-15. Its basic syntax for a custom domain's two CNAME records ends every target in <DynamicPartitionCharacter>-v1.dkim.mail.microsoft, and it defines that value in three sentences: "A dynamically generated character that's used for both selectors (for example, r or n). The value is automatically assigned by Microsoft when you add a new custom domain and enable DKIM. The value is determined by Microsoft's internal routing logic and isn't configurable."
The next line draws the boundary this note is about: "This value is part of the updated DKIM record format for new custom domains in Microsoft 365 introduced in May 2025. Existing custom domains and initial domains continue to use the old DKIM format". The old format, as the page prints it, ends in the initial domain itself. The same passage adds: "The old and new formats can't coexist for the same selector."
Above both templates sits an Important callout that scopes every value on the page: "The values presented in this article are for illustration only." The real values come from the Defender portal's DKIM details for the domain, or from Exchange Online PowerShell.
| Item | Old format | New format, from May 2025 |
|---|---|---|
| Applies to, in the page's words | Existing custom domains and initial domains | New custom domains |
| selector1 target as the page prints it | selector1-contoso-com._domainkey.contoso.onmicrosoft.com | selector1-<CustomDomainWithDashes>._domainkey.<InitialDomainPrefix>.<DynamicPartitionCharacter>-v1.dkim.mail.microsoft |
| Partition character | None in the printed example | Assigned by Microsoft, not configurable |
| Where the real value comes from | The Defender portal DKIM details for the domain, or Get-DkimSigningConfig | |
Why it is easy to get wrong
The phrase "introduced in May 2025" reads naturally as a tenant cutoff. The sentence that carries the date names domains instead: new custom domains on one side, existing custom domains and initial domains on the other. The paragraph never mentions tenant age, so the age of a tenant is no guide to the format a given domain carries. A working record copied from a blog post, a support ticket or a colleague's tenant shows only which format that other domain received.
The page also pulls in two directions. Its troubleshooting entry for a domain mismatch shows a correct target ending in n-v1.dkim.mail.microsoft beside a common mistake ending in contoso.onmicrosoft.com, and its DNS provider examples state: "Your actual values include a dynamic partition character assigned by Microsoft." Both hold for a domain on the new format. For an existing custom domain, which the syntax section keeps on the old format, a reader who takes either statement literally could discard a correct value. The page also leaves "new" and "existing" undefined: it does not say whether the line falls at the date a domain was added or at the date its DKIM signing was first set up.
What it costs
The page's troubleshooting entry for this failure gives the symptom as "DKIM status shows CnameMissing or DKIM signing fails", the cause as "The CNAME target value doesn't match what Microsoft 365 generated", and the fix as "Always use the exact CNAME values from the Defender portal or PowerShell. Don't construct them manually".
Where the record has never matched, the domain stays in the state the page describes before any configuration, in which "no DKIM signing occurs for outbound mail from custom domains". The page also states that "DKIM passes DMARC validation only if the domain that DKIM signed the message and the domain in the From address align", so for as long as that lasts, DKIM contributes no DMARC pass for mail sent from that domain.
Prerequisites
An Exchange Online PowerShell session with an account permitted to run Get-DkimSigningConfig. The Get-DkimSigningConfig reference says only "You need to be assigned permissions before you can run this cmdlet" and points to Microsoft's procedure for finding the required permissions, so this note does not name a minimum role. A Windows machine with Resolve-DnsName from the DnsClient module. No change window, because nothing below writes.
Expected output
Replace contoso.com with the custom domain in question. Each custom domain carries its own pair of records, so run the reads once per domain:
# Read-only. Lists every domain that has a DKIM signing configuration.
Get-DkimSigningConfig | Format-List Name,Enabled,Status,Selector1CNAME,Selector2CNAME
# Read-only. The CNAME targets Microsoft 365 expects for one custom domain.
Get-DkimSigningConfig -Identity contoso.com | Format-List Name,Enabled,Status,Selector1CNAME,Selector2CNAME
# Read-only. What the configured DNS servers return for each selector.
Resolve-DnsName -Type CNAME -Name selector1._domainkey.contoso.com
Resolve-DnsName -Type CNAME -Name selector2._domainkey.contoso.com
The first command is the page's own listing step. The initial domain usually does not appear in it: the page says that "unless you manually configured DKIM signing for the *.onmicrosoft.com domain in the Defender portal or in PowerShell, the *.onmicrosoft.com doesn't appear in the output of Get-DkimSigningConfig."
In the second command, Selector1CNAME and Selector2CNAME are the values to publish, whichever of the two shapes they take. In the page's own procedure, a domain that is not yet signing can appear with Enabled False and a Status of NoDKIMKeys or CnameMissing, or not appear at all. The two Resolve-DnsName reads show what DNS returns today, and a target there that differs from the tenant's value is the exact condition the troubleshooting entry describes: "The Get-DkimSigningConfig output shows different values than what's in DNS."
flowchart TD
accTitle: Which DKIM CNAME target a custom domain needs
accDescr: Microsoft's page puts new custom domains on the target ending in dkim.mail.microsoft and existing custom domains and initial domains on the target ending in onmicrosoft.com. Both branches lead to the same step, reading Selector1CNAME with Get-DkimSigningConfig and comparing it with DNS, which ends in Monitor when they match and Act now when they differ.
A[Custom domain to sign] --> B{Which format?}
B -->|New custom domain| C[Ends dkim.mail.microsoft]
B -->|Existing domain| D[Ends onmicrosoft.com]
C --> E[Read Selector1CNAME]
D --> E
E --> F{Matches DNS?}
F -->|Yes| G[Monitor]
F -->|No| H[Act now, replace CNAME]Side effects
None from the commands. The reference describes Get-DkimSigningConfig as the cmdlet "to view the DomainKeys Identified Mail (DKIM) signing policy settings for domains in a cloud-based organization", and the Resolve-DnsName reference says it "performs a DNS query for the specified name". Neither changes anything in the tenant or in DNS. One timing note: the page says a key rotation "takes four days (96 hours) for the new private key to start signing messages", so a read taken inside that window describes a rotation that has not finished.
Rollback
The reads need no rollback. If a CNAME was already published from a built value and the domain shows CnameMissing, the correction is a DNS change made outside this runbook: replace each selector record with the Selector1CNAME or Selector2CNAME value the read returned, then run the reads again. The page notes that "DNS propagation can take a few minutes to 48 hours depending on your DNS provider and TTL settings", and its advice for a status that stays CnameMissing after 48 hours is to "Double-check the values by using Get-DkimSigningConfig output."
Limitations
The check shows that the published record matches what Microsoft 365 expects today, for the one domain queried. The page says "Each domain or subdomain that sends email needs its own pair of DKIM CNAME records", so a second domain on the same tenant needs its own read and may carry the other format.
It does not show that mail is being signed. The page's verification procedure sends a message to another email system and reads the Authentication-Results header field, which "should include DKIM=pass or DKIM=OK". It also does not settle DMARC: the page lists "DKIM passes but DMARC still fails" as a separate issue, caused when "the d= domain in the DKIM signature doesn't match the From address domain".
It cannot say which format a domain will get before its DKIM signing is first set up, because the page does not publish that rule. And by default Resolve-DnsName asks the machine's own resolvers; its reference says "By default the interface DNS servers are queried if this parameter is not supplied." Where an internal DNS server answers for the same zone, add -Server with a public resolver so the read reflects what the internet sees.
The ITSailor deliverability checker reads the DNS side of the same question from outside a tenant: published SPF and DMARC records, and DKIM keys at common selector names including selector1 and selector2. It cannot see the tenant side, which is what Get-DkimSigningConfig adds.
Sources and further reading
Turn the procedure into a tenant decision.
The Architecture Workshop maps the checks, side effects, and rollback path to your own Microsoft 365 environment.
Review the workshopMore from Ops Log
The Google Workspace scope for reading a leaver's app grants is not read-only
Listing a Google Workspace user's third-party app tokens needs admin.directory.user.security, the same scope that deletes them, and Google lists no read-only variant. Microsoft Graph lists the equivalent grants with Directory.Read.All. Treat the Google credential as a revocation key.
The Azure role called Cost Management Reader is not read-only
Cost Management Reader is described as able to view cost data, yet its action list carries a Microsoft.Support wildcard that includes creating and updating support tickets. The built-in Reader role matches it on every Cost Management feature and cannot write a ticket.
An Azure vCPU family quota can show ten cores free while every size in that family is restricted for the subscription
az vm list-usage reports vCPU quota per VM size family. Measured 2026-09-15 on one subscription: a family read 0 of 10 vCPUs used while all 10 of its sizes carried a NotAvailableForSubscription restriction in the same region. Check az vm list-skus with --all before planning.