Отправляем почту, чтобы она не попадала в спам

Для того, чтобы грамотно обеспечивать рассылки посетителям Вашего сайта, необходимо принять ряд мер. Кроме правильного содержания письма, в котором нежелательны ссылки на внешние ресурсы и прикрепленные файлы (в том числе изображения), следует побеспокоиться о грамотной настройке SPF и DKIM. Тем более, за их отсутствие принимающий почтовый сервер очень сильно «штрафует». Об этом и поговорим.

Настройка SPF записи

SPF, или Sender Policy Framework (инфраструктура политики отправителя), наверное, самое главное, что требует настройки. По сути, что SPF, что DKIM служат одной простой цели: удостовериться в том, что отправитель (то есть вы), разрешили отсылку почты с указанного домена. Работает механизм очень просто: в DNS зону добавляется поле типа TXT, со специальным синтаксисом. В нем указано, с каких именно IP адресов разрешается отправлять почту.

Как работает SPF? Когда на принимающий MTA приходит письмо, он запрашивает записи TXT для домена, от имени которого отправляется почта, ищет среди них тип SPF. Если, в ходе проверки, владелец домена разрешил отправку почты с IP адреса нашего сервера, то SPF тест считается успешно пройденным.

Простейший вариант записи:

v=spf1 a ~all

Или ее полный вид, для сервера Bind:

@ IN TXT “v=spf1 a ~all”

Сначала, уточняется версия spf, в данном случае 1. Дальше идет символ «а», который разрешает отправку почты с любого IP адреса, указанного в DNS зоне, типа А. Достаточно логично! В конце идет тип all, который определяет действие по умолчанию, если до него не было найдено совпадений. Знак тильда говорит о нестрогом запрете (SoftFail), то есть владелец домена запрещает отправку почты, но все же окончательное решение принимает целевой почтовый сервер.

Примеры SPF записей:

Разрешить отправку почты с IP адресов, которые указаны в записях А и MX для текущего домена. Всем остальным — запрещено.

@ IN TXT “v=spf1 +a +mx -all”

Та же самая запись, но опущен знак «+», поскольку по умолчанию действие «разрешить». Следующая запись, полностью аналогична предыдущей.

@ IN TXT “v=spf1 a mx -all”

Мы можем указать конкретный IPv4 адрес, в качестве разрешенного

v=spf1 +ip4:1.2.3.4 –all

Или даже с маской подсети

v=spf1 +ip4:1.2.3.4/24 –all

А вот такая запись вообще не имеет никакого смысла! Будьте осторожны!

spf1 +a +all

Кстати, для тех, кто плохо знаком с настройками DNS зоны, обычно такую возможность предоставляет регистратор домена, в личном кабинете. Эти настройки, чаще всего, вообще не имеют никакого отношения к хостингу.

Настройка DKIM записи

С этим методом дела обстоят чуть сложнее. По своей сути, DKIM представляет из себя электронную подпись, которая добавляется в заголовки письма. Многие почему-то думают, что ее можно добавить исключительно средствами почтового сервера. И на шаред (shared) хостингах испытывают большие трудности, общаются с саппортом, который бывает тоже плохо разбирается в вопросе. На самом же деле, заголовки можно сгенерировать программно, прямо в скрипте PHP.

Для этого удобно воспользоваться библиотекой-классом PHPMailer. Можно написать свою реализацию, если есть желание с головой погрузиться в изучение данного механизма. Уверен, в арсенале других языков программирования похожая библиотека тоже имеется.

Как работает DKIM? Владелец домена создает пару ключей, private и public. Последний размещается в DNS зоне, в записи типа TXT, как и в случае SPF. Отправитель выбирает, какие элементы будут подписаны с помощью private ключа. Это могут быть отдельные заголовки, например From, или же все письмо целиком. Элементы, которые участвуют в подписи, не могут быть изменены в будущем, в том числе во время пересылки. Затем подпись добавляется в заголовки.

Когда принимающий сервер видит в заголовках подпись DKIM, он извлекает указанную запись из DNS зоны домена-отправителя; проверяет подпись с помощью public ключа, который мы там разместили. Убеждается, таким образом, что письмо отправлено с ведома владельца домена и не было изменено во время пересылки. Поскольку подписать можно было только с помощью парного private ключа, держателем которого Вы являетесь, и никак иначе. Можете отдельно почитать, как работает электронная подпись, такой же принцип, но с незначительными отличиями.

Раз мы уже поняли, что DKIM требует пары ключей, давайте их сгенерируем при помощи OpenSSL. Длину ключа будем брать 1024, чтобы не напрягаться с ограничениями TXT записи.

# openssl genrsa -out private.key 1024
# openssl rsa -in private.key -pubout -out public.key

Теперь идем и редактируем зону, добавляем туда два поля. Одно будет отвечать за политику DKIM, второе содержать public ключ:

_domainkey TXT o=~; [email protected];
mailkey._domainkey TXT v=DKIM1; k=rsa; t=s; p=MIG…QAB

Как это выглядит в панели управления DNS зоной, одного из регистраторов:

Тоже самое, для файла зоны сервера Bind:

_domainkey.yourdomain.org. IN TXT “o=~; [email protected]”
mailkey._domainkey.yourdomain.org. IN TXT “v=DKIM1; k=rsa; t=s; p=MIG…QAB”

Обратите внимание, что в файле public.key, нужно удалить первую и последнюю строки (——BEGIN PUBLIC KEY——, ——END PUBLIC KEY——), а из самого ключа убрать перенос строк, перед тем как копировать его в TXT запись.

Разберем, что означают флаги для первой записи (политика DKIM):

o=~ — некоторые письма от этого домена подписываются. Можно указать, что должны подписываться все, заменив «~» на «-».

r – содержит email адрес, куда будут направляться письма от принимающего сервера с отчетом, если проверка DKIM не пройдет.

t – режим тестирования. Установите его в «y», в случае необходимости, тогда DKIM проверка будет отключена. Не рекомендуется. Поле не обязательное.

n – содержит пояснения для технических специалистов, кто будет разбираться в записях. У нас отсутствует. Поле не обязательное.


Теперь о записи с самим ключом. Обратите внимание, mailkey – так называемый селектор. Он указывается в заголовках письма. Таким образом, принимающий почтовый сервер «знает» какую именно DNS запись смотреть, в случае если там несколько ключей для разных серверов-отправителей.

v – тут все просто, указываем версию

k – тип подписи. По умолчанию rsa, он поддерживается всеми серверами.

t – режим тестирования. В нашем случае в значении «s», говорит о том, что почту мы отправляем только с основного домена. Другими словами, мы запрещаем отправку почты с субдоменов.

n – тоже самое, что для предыдущей записи. Можем указать комментарий. Не обязательное поле.

p – сам public ключ, в виде одной строки без переносов. После него не ставится «;», поскольку в нашем случае он идет последним.

Настройка DMARC записи

После настройки записей SPF и DKIM, желательно, так же прописать правило DMARC. Здесь задаются политики, если проверки с помощью вышеозначенных механизмов не прошли.

В нашем случае указываем

_dmarс.yourdomain.org. IN TXT “v=DMARC1; p=none”

Подробнее о флагах хорошо написано тут https://support.google.com/a/answer/2466563?hl=ru

Как проверить отправляемые письма на спам?

Существует замечательный сервис для проверки отправляемых вами писем на предмет того, как они проходят СПАМ фильтры и вообще как их «видит» типичный MTA сервер.

https://www.mail-tester.com/

И еще, если занимаетесь официальными рассылками для своих клиентов, очень желательно предусмотреть механизм отписки. Подробнее тут: https://geektimes.ru/post/101440/

Если планируете сообщения в формате HTML, не забудьте дублировать их чистым текстом (plain text).

Пример отправки HTML писем с DKIM подписью средствами PHP. Для удобства, используем шаблонизатор Smarty и библиотеку PHPMailer.

  1. public function sendMail($config, $entity)
  2. {
  3. $config = array_merge($this>defaultConfig, $config);
  4. $this>smarty>assign(‘entity’, $entity);
  5. $config[‘messageHTML’] = $this>smarty>fetch(‘mails/’.$config[‘template’].‘_html.tpl’);
  6. $config[‘messagePLAIN’] = $this>smarty>fetch(‘mails/’.$config[‘template’].‘_plain.tpl’);
  7. $mail = new PHPMailer(false);
  8. $mail>setLanguage(‘ru’);
  9. $mail>CharSet = ‘utf-8’;
  10. $mail>From = $config[‘from’];
  11. $mail>FromName = $config[‘fromname’];
  12. $mail>Sender = $config[‘from’];
  13. $mail>AddAddress($config[‘to’], $config[‘toname’]);
  14. $mail>Subject = $config[‘subject’];
  15. // Добавить картинку в письмо. Не рекомендуется.
  16. // $mail->AddEmbeddedImage(PUBLICROOT . ‘/images/logo_small.png’, ‘logo’, ‘logo_small.png’);
  17. $mail>Body = $config[‘messageHTML’];
  18. $mail>IsHTML(true);
  19. $mail>AltBody = $config[‘messagePLAIN’];
  20. $mail>DKIM_domain = «zhostovoart.com»;
  21. $mail>DKIM_private = «/etc/DKIM/domain/rsa.private»; //path to file on the disk.
  22. $mail>DKIM_selector = ‘mailkey’; //тот самый селектор, который в DNS зоне
  23. $mail>DKIM_passphrase = »; //если генерировали ключ с паролем, указать.
  24. $mail>DKIM_identifier = $mail>From;
  25. $mail>Send(); //Отправляем.
  26. // $a = $mail->CreateBody(); //Посмотреть получившееся сообщение
  27. //echo $a;
  28. }