Как найти причину, если письма уходят без DKIM
Если в полученном письме нет DKIM-Signature, выясняйте, где оно обошло подписывающий сервис или почему тот не смог прочитать ключ. Если заголовок есть, но получатель показывает dkim=fail, проверяйте DNS-ключ и изменения письма после подписи. Отсутствие DKIM само по себе не означает, что письмо гарантированно попадёт в спам; ниже — мой порядок диагностики и исправления.
Что означает отсутствие DKIM и чем оно грозит
DKIM связывает домен подписанта с криптографической подписью сообщения. Получатель берёт открытый ключ из DNS и проверяет подписанные заголовки и тело письма. Это помогает обнаружить изменения после подписи и понять, какой домен взял ответственность за сообщение. Но DKIM не подтверждает, что письмо доброкачественное, и не обещает доставку во «Входящие». SPF проверяет разрешённый сервер отправки, DMARC задаёт правила обработки и выравнивание доменов. Эти механизмы дополняют друг друга; один зелёный результат не заменяет остальные.
Разделяйте два симптома. Если в полном исходнике письма отсутствует DKIM-Signature, письмо, вероятно, не прошло через подписывающий компонент либо компонент не добавил подпись. Если заголовок присутствует, но результат проверки — fail, подпись создана, однако получатель не смог её подтвердить. Тогда смотрю на selector и домен d= в DKIM-Signature, соответствующую запись DNS, а также на то, менялось ли сообщение после подписания. Никакого правила «нет DKIM — значит спам» нет: решение о папке зависит от правил получателя и репутации отправителя. Для общей настройки корпоративной почты мы сначала проверяем весь путь письма, а не только TXT-запись. Проверка подписи и политика доставки — разные этапы. Даже корректная криптографическая подпись не является белым списком: получатель может учитывать жалобы, объём отправки, репутацию домена и соответствие требованиям своей почтовой системы. Поэтому я фиксирую отдельно технический результат DKIM и отдельно то, куда доставлено сообщение. Так мы не принимаем совпадение за причинно-следственную связь и не обещаем, что один исправленный механизм отменит все остальные проверки.
Важно не смешивать «подписать письмо» и «проверить чужую подпись»: OpenDKIM может быть настроен на оба режима, но у исходящего потока должна быть включена именно подпись. Результат входящей проверки или наличие процесса в списке служб не доказывают, что он подписывает исходящие сообщения. Проверьте режим и правила выбора домена/ключа в конфигурации, затем подтвердите результат на новом письме. Я не начинаю с правок DNS, пока не выяснил, какую операцию реально выполняет установленный фильтр.
- DKIM-Signature отсутствует — проверяйте маршрут и работу подписанта.
- Подпись есть, dkim=fail — проверяйте ключ, селектор и изменения сообщения.
- dkim=pass — подпись проверена, но доставка всё ещё зависит от других факторов.
Сначала проследите путь конкретного письма
Я беру одно письмо с проблемой и сравниваю его с письмом, которое подписывается. Важно сохранить полный исходник: заголовки, дату, адрес отправителя и результат проверки получателя. Отмечаю, откуда письмо было отправлено — из почтового клиента, приложения на сайте, CRM или скрипта. Затем выясняю, куда именно этот источник передал сообщение: на локальный MTA, через SMTP-релей или прямо на внешний сервер. Разные приложения нередко используют разные маршруты, хотя пользователю кажется, что «почта у нас одна».
В случае сети «Берест» часть обычной корреспонденции проходила через настроенный сервер, а уведомления сайта шли отдельным путём. Поэтому проверка одного удачного письма создавала ложное чувство порядка. Я разделил сообщения по источнику и увидел, что проблемные уведомления не проходили через компонент подписи. После этого проверили права доступа к закрытому ключу и подключение нужного маршрута к MTA. Это хороший диагностический пример, но не универсальный рецепт: конкретный сервис и способ интеграции зависят от конфигурации. Сначала установите, кто фактически отправил тестовое письмо; потом исправляйте именно этот путь. Для сравнения используйте письма одного типа и не редактируйте исходник перед проверкой. Пересылка вручную, копирование содержимого в новый черновик или просмотр сокращённых заголовков в интерфейсе клиента могут скрыть важную часть картины. Удобнее отправить письмо на контролируемый тестовый ящик и сохранить оригинал в формате, где видны все заголовки. Запишите, каким приложением оно отправлено, и повторите точно тот же сценарий после каждого изменения. Иначе легко сравнить разные сообщения и сделать неверный вывод.
Полезно составить маленькую матрицу: источник отправки по строкам, наличие DKIM-Signature и dkim=pass по столбцам. Например, отдельно проверяются письмо клиента, уведомление сайта и письмо из CRM — только если такие источники действительно используются. Так видно, проблема общая или привязана к одному приложению. Если все письма без подписи, проверяйте общий путь и сервис; если не подписан один источник, сравнивайте его SMTP-настройку и маршрут. Матрица из нескольких тестов надёжнее одного случайного примера.
- Сравните исходники рабочего и проблемного писем.
- Зафиксируйте источник и маршрут отправки.
- Проверьте, что маршрут проходит через подписывающий компонент.
Когда OpenDKIM не может прочитать ключ
Если отдельно нужна проверка DKIM-ключа, начните с текущего источника и селектора. Для OpenDKIM проверьте, что в конфигурации указан существующий файл закрытого ключа и что процесс службы вправе пройти по каталогам и прочитать сам файл. Право на чтение файла недостаточно, если один из родительских каталогов закрыт для пользователя службы. И наоборот, широкие права на секретный ключ — плохой способ «починить» доступ. Сверяйте владельца, группу и права с тем, как именно запускается сервис в вашей системе. Каталог конфигурации и каталог ключей зависят от дистрибутива и способа установки, поэтому путь из чужой инструкции не следует считать стандартом для любого сервера.
В журнале ищите сообщения о невозможности открыть ключ, ошибках доступа или недоступной конфигурации; точный текст зависит от сборки и системного журнала. Затем сопоставьте файл из конфигурации с реальным путём, проверьте права на каждом каталоге и убедитесь, что процесс OpenDKIM запущен. Не трактуйте фразу selector not found как универсальный дословный текст ошибки: выясните по журналу, что именно не найдено — локальное сопоставление селектора и ключа или публичная DNS-запись. После изменения конфигурации перезапустите соответствующую службу, если этого требует способ управления ею, и отправьте новое тестовое письмо. Перезапуск сам по себе не исправит неверный путь. У ключа есть две стороны: закрытая используется для подписи и хранится на сервере, открытая публикуется в DNS для проверки. Если они не соответствуют, получатель не подтвердит созданную подпись, даже когда файл доступен службе и письмо прошло через нужный компонент. Не заменяйте ключ поспешно: сначала выясните, какой selector реально указан в сообщении и какой ключ ожидает запись зоны. При ротации координируйте публикацию и переключение подписанта, чтобы тестовое письмо не оказалось подписано уже новым ключом при ещё не опубликованном DNS-значении.
У OpenDKIM способ сопоставления адреса отправителя, домена, селектора и файла ключа зависит от выбранной схемы. В одной конфигурации значения заданы напрямую, в другой применяются таблицы KeyTable и SigningTable. Не добавляйте сразу все директивы из найденного руководства: разные варианты настройки могут быть взаимоисключающими. Сначала прочитайте конфигурацию установленной версии и выясните, какая схема там используется. Затем проверьте, что нужный адрес отправителя сопоставляется с ожидаемым селектором и существующим файлом, иначе служба может быть исправна, но не выбрать ключ для конкретного письма.
- Сверьте настроенный путь с существующим ключом.
- Проверьте доступ службы к файлу и каталогам.
- Сопоставьте selector в настройке и DKIM-Signature.
Проверьте DNS и результат проверки подписи
В DKIM-Signature найдите selector в параметре s= и домен подписанта в d=. По имени selector._domainkey.домена подписанта должна находиться опубликованная запись с открытым ключом, соответствующим закрытому ключу, которым подписывают письмо. Сравните запись именно для того домена, который указан в d=; запись другого домена или прежнего селектора не подойдёт. Проверьте ответ авторитетной DNS-зоны и убедитесь, что значение не обрезано при публикации. Не выкладывайте закрытый ключ в DNS и не отправляйте его в переписке: наружу публикуется открытый ключ.
Заголовок Authentication-Results формирует принимающая сторона; это не обязательная часть исходящего письма, созданная вашим сервером. В нём смотрите результат DKIM и домен, к которому он относится. Отсутствие Authentication-Results в просмотре не доказывает, что отправитель не подписал письмо: заголовок может отсутствовать в конкретном исходнике или отображении клиента. Для исходящей диагностики важнее найти DKIM-Signature в полном исходнике, а результат dkim=pass или dkim=fail читать в сообщении, принятом тестовым ящиком. Сравните этот результат с опубликованным ключом и сохранённым исходником, не меняя запись DNS наугад. Общие роли SPF, DKIM и DMARC разобраны в материале о настройке трёх механизмов. DNS-проверка должна учитывать делегирование домена и то, кто управляет зоной: запись могла быть добавлена в панели неавторитетного DNS-провайдера и потому не видна получателям. Сверяйте фактический ответ публичного DNS с данными у владельца зоны, а не только наличие строки в интерфейсе управления. Если вы только что изменили запись, учитывайте срок её кэширования и проверяйте результат повторно. Не путайте задержку обновления с ошибкой подписи: отсутствие нужного открытого ключа объясняет fail, но не отсутствие заголовка DKIM-Signature в исходящем письме.
Удобная проверка — сопоставить ключ, который настроен для подписи, с ключом, который опубликован по имени селектора. Если используется ротация, старый и новый селекторы могут сосуществовать: важно знать, каким из них подписано именно тестовое сообщение. Смена открытого ключа в панели DNS не переписывает уже созданные письма и не меняет селектор в настройке подписанта. Поэтому смотрите на фактические параметры s= и d= в сообщении, а затем проверяйте соответствующую запись зоны. Это снимает частую путаницу между «ключ поменяли» и «письмо подписывается новым ключом».
- s= и d= — из DKIM-Signature проблемного письма.
- DNS-имя строится из селектора и домена подписанта.
- Проверяйте оценку принимающей стороны в Authentication-Results.
Кириллица обычно не виновата: ищите изменения после подписи
Кириллица в теме письма или адресуемых пользователю заголовках сама по себе не является причиной отказа DKIM. Заголовки должны соответствовать формату электронной почты, а подписант и проверяющая сторона применяют предусмотренную стандартом нормализацию. Совет «замените всё на ASCII» маскирует настоящую причину и портит письмо. Проверяйте, корректно ли приложение формирует MIME-заголовки, и сравнивайте сообщение на выходе подписанта с тем, что получил тестовый ящик. Смотрите не на язык текста, а на изменение подписанных данных.
DKIM может перестать проходить, если после подписи промежуточный сервис изменил подписанное поле или тело сообщения: например, добавил футер, переписал тему, изменил MIME-структуру или преобразовал вложение. Сравните body hash bh= и набор заголовков из h= в исходнике, а также изучите маршрут через шлюзы и рассыльщики. RFC описывает проверку канонизированной версии письма; изменение допустимо не всегда и зависит от алгоритма canonicalization. Исправляйте этап, который меняет уже подписанное письмо, либо организуйте подпись после последней такой модификации. Это точнее, чем объявлять виноватой кодировку. В журнале сопоставляйте событие с временем отправки и идентификатором письма, если MTA его показывает. Общие строки «служба активна» недостаточны: процесс может работать, но не получать конкретную категорию сообщений. И наоборот, отсутствие ошибки в журнале не доказывает, что подписант был вызван. Именно поэтому я соединяю наблюдения из трёх мест: исходник полученного письма, журнал сервиса подписи и конфигурацию маршрута в MTA. Это позволяет отличить отказ чтения ключа от ситуации, когда приложение вообще не передало письмо на сервер, который умеет подписывать.
Не всякое изменение после отправки ломает DKIM: это зависит от того, какие поля подписаны и какой способ канонизации указан. Однако изменение тела обычно влияет на проверку хеша тела, а изменение подписанного заголовка — на подпись заголовков. Поэтому сохраняйте исходник до прохождения шлюза и после него, если можете получить обе копии. Сравнение покажет, на каком этапе возникло расхождение. Если промежуточный сервис добавляет юридический футер или переписывает MIME-части, переставьте подписание после этой операции либо настройте процесс так, чтобы письмо больше не менялось.
- Сравните письмо на выходе отправителя и на входе тестового ящика.
- Проверьте изменения тела, MIME и подписанных заголовков.
- Не удаляйте кириллицу без доказанной ошибки формата.
Мой порядок исправления и контроль результата
Я фиксирую тестовый сценарий: один отправитель, один адрес получателя, одно письмо с понятной темой. Сохраняю полный исходник и записываю время отправки. Сначала проверяю, появился ли DKIM-Signature; если его нет, возвращаюсь к маршруту и журналу подписанта. Если заголовок появился, сверяю s= и d= с DNS и читаю Authentication-Results на стороне тестового получателя. Затем проверяю, не меняет ли письмо промежуточный шлюз. Так у каждой ветки есть наблюдаемый симптом и конкретная следующая проверка, а не бесконечное вращение настроек.
В кейсе «Берест» мы проверили оба направления: доступ службы к ключу и маршрут уведомлений сайта. После исправлений я отправил новые тесты отдельно из почтового клиента и сайта, сохранил результаты проверки и убедился, что подпись присутствует на обоих маршрутах. Это не означает, что все письма теперь гарантированно окажутся во «Входящих»: SPF, DMARC, репутация, жалобы и содержание сообщения оцениваются отдельно. Для контроля достаточно периодически отправлять тесты с каждого источника и проверять заголовок и результат на стороне получателя. Мониторинг имеет смысл настроить на реальные признаки сбоя — пропавшую подпись или неуспешную проверку, а не на само наличие кириллицы. После проверки сохраните рабочую схему: откуда отправляет каждое приложение, через какой SMTP-сервер оно идёт, где применяется подпись и какой тест подтверждает результат. Документируйте не секретный материал, а владельца настройки, имя селектора, домен записи и способ безопасной ротации ключа. При обновлении системы повторяйте контрольную отправку с каждого источника. Письмо с сайта и письмо из почтового клиента — два разных теста, даже если в поле From указан один адрес. Такая короткая запись экономит время при следующем изменении и помогает не публиковать закрытый ключ в задаче или тикете.
После восстановления я документирую ожидаемый результат для каждого источника: подпись есть, домен d= соответствует плану, селектор разрешается в DNS, а контрольный получатель сообщает pass. Отдельно отмечаю, что именно ещё влияет на доставку, чтобы успешный тест DKIM не превратился в обещание «спам исчезнет навсегда». Если организация меняет почтовый шлюз, DNS-провайдера или приложение для рассылок, этот сценарий стоит повторить. Изменение маршрута часто незаметно пользователю; контрольный тест быстро показывает, что новое письмо больше не проходит через прежнюю точку подписи.
- Нет подписи: маршрут → служба → доступ к ключу.
- Есть fail: селектор и DNS → изменения после подписи.
- Есть pass: отдельно оценивайте SPF, DMARC и доставляемость.
Частые вопросы
Почему OpenDKIM не добавляет DKIM-Signature?
Письмо может обходить сервис подписи, служба может не запуститься или не иметь доступа к закрытому ключу. Сравните маршрут проблемного письма с тем, которое подписывается, и проверьте журнал службы.
Отсутствие DKIM гарантирует попадание письма в спам?
Нет. Получатель учитывает собственные правила и другие сигналы. Отсутствие аутентификации может ухудшить доставку или привести к отклонению по политике получателя, но результат не универсален.
Почему DKIM-Signature есть, а результат dkim=fail?
Проверьте селектор и домен подписанта в DNS, соответствие открытого и закрытого ключей и изменения письма после подписания.
Может ли кириллица в теме сломать DKIM?
Сама по себе кириллица не является причиной. Проверяйте корректность MIME-заголовков и изменения подписанных данных после подписи.
Нужно ли перезапускать Postfix и OpenDKIM?
После изменения конфигурации перезапустите или перечитайте настройки той службы, к которой относится изменение, согласно документации вашей системы. После этого отправьте новое тестовое письмо.
Источники
- RFC 6376 — DomainKeys Identified Mail (DKIM) Signatures — Проверено назначение подписи, DNS-поиск открытого ключа, обработка заголовков и тела, а также последствия изменений сообщения: https://datatracker.ietf.org/doc/html/rfc6376
- Debian Manpages — opendkim.conf(5) — Руководство по конфигурации OpenDKIM: пути ключа, KeyTable и SigningTable; проверено, что способ настройки зависит от выбранной схемы: https://manpages.debian.org/bookworm/opendkim/opendkim.conf.5.en.html
- Postfix Milter README — Официальное описание интеграции внешних проверяющих и подписывающих компонентов с Postfix: https://www.postfix.org/MILTER_README.html
- Google Email sender guidelines — Официальные требования и рекомендации для отправителей; отсутствие аутентификации может повлиять на классификацию и приём, но не означает гарантированный спам: https://support.google.com/mail/answer/81126?hl=en



