Короткий ответ

Для домена contoso.example в Exchange Online нужны две CNAME (selector1._domainkey и selector2._domainkey) на имена вида selector1-contoso-example._domainkey.contoso.onmicrosoft.com, плюс включённая подпись в конфигурации DKIM тенанта. Пока CNAME даёт NXDOMAIN, Microsoft не сможет крутить ключи, даже если вы «включили галочку». Проверка факта — заголовок исходящего письма: dkim=pass и d=contoso.example (alignment с From). Не генерируйте руками RSA в BIND «как на postfix», если контур — Exchange Online: ключ живёт у Microsoft, в DNS только CNAME.

dkim=none значит подписи нет. fail — подпись есть, но ключ/тело/заголовки не сходятся (чужой селектор, переписанный шлюз, обрезанный MIME).

Симптомы и как отличить

  • Письма из OWA без DKIM-Signature, либо s=selector1 при NXDOMAIN на этом селекторе.
  • В Defender portal / EAC статус DKIM для contoso.example не Enabled.
  • CNAME указывает на чужой fabrikam.onmicrosoft.com после копипаста инструкции.
  • Сторонний ESP ставит свою подпись d=esp.example, а From — contoso.example: для Microsoft это «не наша» подпись, для DMARC может не выровняться.
ЗаголовокЗначение
dkim=noneEO не подписал или письмо не из EO
dkim=pass header.d=contoso.exampleцелевое состояние для корпоративного From
dkim=failключ не тот, тело изменено после подписи, битый селектор
pass d=crm.net, From contosoдля DMARC нужен второй pass с вашим d= или SPF alignment

От SPF отличайте: SPF может pass при dkim=none. От спама: fail DKIM ухудшает классификацию, но Delivered+Junk — ещё и репутация.

Возможные причины

  1. CNAME не созданы или с опечаткой в дефисах (contoso.examplecontoso-example в целевом имени).
  2. Подпись в тенанте выключена: Get-DkimSigningConfigEnabled : False.
  3. DNSSEC/прокси Cloudflare «оранжевым облаком» на CNAME _domainkey ломает ответ. Для DKIM нужен DNS-only, не HTTP-proxy (это не веб).
  4. Старый селектор после ротации, кэш резолвера у получателя (редко держится долго).
  5. Промежуточный шлюз переписывает Subject/тело после подписи EO (подписной дисклеймер на on-prem).
  6. Письмо ушло с contoso.onmicrosoft.com как подписываемый домен, а From кастомный без Enabled config.
  7. Пользователь шлёт через SMTP AUTH устройство, которое не попадает в EO signing path (прямой 25).

Диагностика

Плейсхолдеры: contoso.example, тенант contoso.onmicrosoft.com.

1. DNS селекторов

Имена CNAME Microsoft показывает в мастере DKIM (Defender portal → Email authentication → DKIM, либо EAC). Типовой вид:

Resolve-DnsName selector1._domainkey.contoso.example -Type CNAME
Resolve-DnsName selector2._domainkey.contoso.example -Type CNAME
nslookup -type=CNAME selector1._domainkey.contoso.example
nslookup -type=CNAME selector2._domainkey.contoso.example

Ожидайте CNAME, не TXT с p=MIIB.... Если видите TXT с ключом — это схема on-prem/ESP, не штатный Exchange Online.

Проверьте, что цель CNAME резолвится:

Resolve-DnsName selector1-contoso-example._domainkey.contoso.onmicrosoft.com -Type TXT

Пустой TXT у цели — ещё не опубликована пара в тенанте или неверный hostname.

2. Конфиг тенанта

Connect-ExchangeOnline -UserPrincipalName admin@contoso.example
Get-DkimSigningConfig -Identity contoso.example |
  Format-List Domain, Enabled, Status, Selector1CNAME, Selector2CNAME

Сверьте Selector1CNAME с тем, что в зоне. Не редактируйте CNAME «на глаз».

3. Живое письмо

Отправьте с ivan.petrov@contoso.example на контрольный ящик. В исходнике:

  • есть DKIM-Signature с d=contoso.example;
  • Authentication-Results содержит dkim=pass.

Message Trace факт подписи не заменяет: Get-MessageTrace покажет Delivered даже при dkim=none.

4. Кто ломает после подписи

Если EO ставит pass, а конечный получатель видит fail — ищите хоп после mail.protection.outlook.com: список рассылки, переписывающий From, «антивирус-шлюз» компании получателя. Это не ваш ключ.

Решение

Сценарий A. CNAME нет / NXDOMAIN

Скопируйте точные имена из Get-DkimSigningConfig в DNS-зону. Подождите TTL. Не создавайте одновременно TXT с ключом на том же узле.

Сценарий B. CNAME есть, Enabled False

После резолва обеих CNAME включите подпись в портале или:

Set-DkimSigningConfig -Identity contoso.example -Enabled $true

Если командлет отказывается — DNS ещё не совпал с ожидаемым (опечатка, внутренний split-brain DNS отдаёт другой ответ, чем публичный).

Сценарий C. Подпись d= другого домена

Включите DKIM именно для Accepted Domain, с которого From. Алиасы на contoso.example при первичном fabrikam.example подписываются по политике домена заголовка From — проверьте, какой домен в From фактически.

Сценарий D. ESP/сайт

Либо делегируйте селектор ESP (s=k1._domainkey TXT/CNAME по их инструкции) рядом с selector1 Microsoft, либо шлите транзакционные письма через Exchange. Два селектора на разных именах не конфликтуют. Конфликт — два разных типа на одном selector1._domainkey.

Сценарий E. Гибрид с дисклеймером

Дисклеймер должен ставиться до финальной подписи или через транспорт, который переподписывает. Классика: on-prem переписывает тело после EO — получатель считает подпись битой. Уберите двойную обработку или подписывайте на последнем хопе.

Как проверить, что проблема устранена

  1. Публичный Resolve-DnsName на оба селектора → CNAME + цель с ключом.
  2. Enabled : True.
  3. Новое письмо из OWA: dkim=pass header.d=contoso.example.
  4. Повтор через 2×TTL с другого резолвера (не кэш офисного DNS).

Контроль доставки — отдельно: спам.

Если не помогло

  • none при Enabled True: письмо шло не через EO (сканер, PHP mail). Сначала путь, потом DNS.
  • fail только у одного получателя: они кешируют старый ключ или портят MIME. Дайте сырой образец.
  • Ротация селекторов Microsoft: оба CNAME должны жить постоянно, не «оставили только selector1».
  • DNSSEC SERVFAIL на _domainkey: чините цепочку DS, не отключайте DNSSEC «навсегда».

Профилактика

  • DKIM включают до DMARC p=reject.
  • Чеклист в подготовке домена.
  • Запрет оранжевого прокси на _domainkey и _dmarc.
  • Мониторинг: периодическое контрольное письмо и парсинг dkim=.
  • Не храните «приватный ключ DKIM Microsoft» — его нет у вас в файле.

FAQ

Нужен ли TXT с p= публичным ключом для Microsoft 365?

Нет, в штатной схеме — CNAME на запись тенанта. TXT p= — типичный self-hosted OpenDKIM.

Можно ли один селектор вместо двух?

Microsoft публикует пару для ротации. Опубликуйте оба, как выдаёт мастер.

selector1 vs selector2 — какой в письме?

Тот, который сейчас активен. DNS должны отвечать оба, иначе ротация упадёт.

Ломает ли пересылка DKIM?

Классический forward часто ломает тело/заголовки. Тогда выручает ARC у добросовестных пересыльщиков. Ваш исходящий DKIM от этого не «чинят» вторым ключом.

Зачем DKIM, если SPF pass?

SPF не покрывает выровненный From, когда Return-Path чужой. DMARC любит DKIM на домене From. См. проверку комплекта.