Установка своего почтового сервера, как правило, не вызывает особых трудностей. В Сети доступно большое количество готовых инструкций. Буквально одна команда, и 25-й порт уже готов к работе. Весело становится, когда отправленные письма начинают возвращаться, а получатели жаловаться, что сообщения не доходят. Здесь уже хочешь не хочешь, но придется искать причины и вникать в технологии.
 

Кто отправляет письма

Сегодня возможность привязать свой домен к сервису предлагают многие веб-службы. Особо популярно размещение почты на Gmail или Яндексе. Все сообщения будут идти через предоставленный ими SMTP-сервер, проверенный поставщик услуг сам сформирует все необходимые заголовки и подписи, которые позволят пройти через любой спам-фильтр. Но такой вариант не всегда возможен. Например, организация имеет большое количество пользователей, нужны особые настройки для почты, недоступные в облачных сервисах. Или используется свой сервер с порталом, CMS или интернет-магазин, с которых нужно отправлять сообщения.

По умолчанию все PHP-приложения используют для отправки почты функцию mail(), которая, в свою очередь, отправляет их через локальный SMTP-сервер, описанный в php.ini.

[mail function]
sendmail_path = /usr/sbin/sendmail -t -i

Или в виртуальном хосте:

php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f webmaster@example.org"

И хотя там в 100% случаев написан sendmail, на самом деле это может быть симлинк, а почту отсылает Postfix или Exim. Чтобы отправить почту из приложения, можно выбрать один из трех вариантов:

  • Сам движок иногда позволяет указать внешний SMTP-сервер (в дефолтных настройках или через плагин, в WordPress это WP Mail SMTP или Easy WP SMTP). Достаточно просто указать данные аккаунта, и все проблемы решены.
  • Использование программы-прокладки, которая эмулирует работу локального SMTP-сервера и отправляет сообщения через почтовый аккаунт на стороннем сервере. Здесь очень популярна SSMTP.
  • Использование своего почтового сервера. Придется, конечно, его настроить, зато больше возможностей конфигурации.

Нас интересует последний вариант. Разберем, как пробиться через антиспам-технологии и гарантированно доставить получателю сообщение. Сами фильтровать спам не будем. Это тема другой статьи. В качестве подопытного SMTP-сервера выберем Postfix и Exim, они популярны на хостингах, просты и понятны в настройках, хотя основные вопросы будут касаться всех SMTP-серверов.

 

Как не попасть в спам

Борьба со спамом — это головная боль всех администраторов почты. Причем в последнее время актуальна как раз обратная сторона медали: спам-фильтры буквально зверствуют. Поэтому спам в приходящей почте практически отсутствует, но вот нормальные сообщения постоянно куда-то пропадают, клиенты и руководство нервничают, и приходится дополнительно убеждаться, что сообщение дошло до адресата. И после установки SMTP-сервера с большой вероятностью придется еще повозиться, чтобы сообщения вообще хоть куда-то доходили. В частности, чтобы оценить настройки, следует посмотреть, доставляются ли письма в ящики основных почтовых систем Gmail, Яндекс, Mail.Ru. Обычно на этом этапе появляются первые сложности, и приходится решать все проблемы персонально.

Почтовые сервисы используют многоуровневую систему фильтрации спама, причем настолько серьезную и засекреченную, что о принципах не знает даже их собственная техподдержка. И у каждого сервиса свои приоритеты. Хотя обычно некая подсказка о причине недоставки содержится в ответном письме сервиса. Также в анализе причин помогает сервис mail-tester.com, достаточно отправить письмо на указанный там адрес и затем после анализа получить результат и перечень проблем. Некоторые из них можно проверить и решить, еще не настраивая SMTP-сервер.

Mail-tester.com — хорошее подспорье в поиске проблем
Mail-tester.com — хорошее подспорье в поиске проблем

Борьба со спамом породила множество технологий. Самая старая из них — blacklist, в который заносятся все IP и домены, занимавшиеся рассылкой спама, сюда же могут попасть открытые релеи, прокси и Dialup-адреса, используемые для удаленного доступа (то есть они теоретически не должны рассылать почту). Организованы такие blacklist по-разному. Популярностью пользуются DNSBL (DNS blacklist) — черные списки в формате DNS, которые легко опрашивать. На сегодня доступно множество баз, не все они популярны и используются. Проблема в том, что списка для конкретного почтового сервиса нет, сколько и какие они опрашивают — это тайна.

Доменные имена, как и IP-адреса, сегодня могут быть «бэушными». Есть вероятность, что до тебя ими пользовался сервис рассылки сообщений или хост, размещенный на нем, был взломан и рассылал спам. Соответственно, они вполне могут попасть в какой-то из DNSBL и быть проблемой. Mail.Ru отбрасывал письма с одного IP именно из-за того, что тот находился в одном из таких полузабытых списков, попав туда в 2010 году. Причем Mail.Ru даже не утруждался проверять правильность SPF и DKIM. Дело сдвинулось, лишь когда IP убрали из блек-листа.

Проверить IP или домен можно самостоятельно, отослав DNS-запрос к выбранному DNSBL-серверу при помощи утилиты dig:

$ host -tA xakep.ru.ex.dnsbl.org
Host xakep.ru.ex.dnsbl.org not found: 3(NXDOMAIN)

Но удобнее пользоваться онлайн-сервисами, проверяющими сразу в нескольких базах. IP можно проверить в dnsbl.info (59 баз) или whatismyipaddress.com (72 базы), домен, кроме того, — в mxtoolbox.com (107 баз), spamhaus.org или multirbl.valli.org. Если вдруг домен или IP окажется в списке, лучше сразу написать в поддержку и убрать свой адрес.

Прогоняем домен по DNSBL-базам
Прогоняем домен по DNSBL-базам
 

Правильная DNS

При получении сообщения удаленный SMTP-сервер анализирует прежде всего его заголовок. Почтовая программа отправляет только From, To, Date, Subject и X-Mailer. Они в общем понятны и просто указывают, от кого и куда слать. Остальной заголовок формируется как SMTP-сервером, так и приложением, его отправляющим. Это, кстати, тоже нужно учитывать, потому что письма, отправляемые через Telnet, могут уходить, а с Roundcube — нет, просто потому, что у них разный заголовок. Roundcube, например, подставляет свой HELO/EHLO на основании переменной server_name или localhost, если она не определена. Поэтому иногда нужно просто задать его явно:

$rcmail_config['smtp_helo_host'] = 'example.org';

То же касается и самописных PHP-скриптов.

При передаче письмо будет проходить минимум через два SMTP-сервера, каждый из которых тоже добавляет что-то от себя в заголовок. В первую очередь каждый сервер добавляет свой Received: from. Читать их лучше снизу вверх. Самое нижнее сообщение — это сервер отправителя, самый верхний — сервер получателя. Хотя на самом деле серверов может быть больше, особенно это актуально при работе с крупными провайдерами услуг, которые, приняв письмо, перебрасывают его дальше, или при использовании на пути SMTP-прокси. Для анализа пути сообщения можно использовать сервис от Google, который покажет в понятной форме все SMTP-серверы, время прохождения и тесты SPF, DKIM и DMARC (о них дальше).

Путь письма
Путь письма

Заголовки Received отличаются, хотя есть общие правила. Типичный выглядит так:

Received: from server.example.org [1.2.3.4] (helo=server.example.org) by st15.provider.com with esmtps (Exim 4.80.1) (envelope-from <mail@example.org>)

Здесь сообщение было получено с сервера, который называется server.example.org, имеет IP 1.2.3.4, в приветствии helo было использовано это же имя, получил его Exim 4.80.1 сервера st15.provider.com. Сообщение отправлено с mail@example.org. Приняв такой заголовок, SMTP-сервер начинает проверять данные. Пробивает домен и IP по базам DNSBL. Проверяет наличие MX-записи у домена. MX изначально используется для поиска почтовых серверов, обслуживающих данный домен, ее наличие подтверждает, что домен отправляет почту.

Дальше он производит обратное разрешение имени по IP через обратный DNS-запрос c помощью PTR-записи. То есть он узнает, сервер с каким именем должен быть по адресу, с которого пришло сообщение. Такое поведение было заложено в RFC 2505 от февраля 1999 года Anti-Spam Recommendations for SMTP MTAs. И хотя давно признано, что обратные зоны не являются достаточным условием для однозначного опознавания отправителя и часто приводят к ошибкам и задержкам, они все же поддерживаются. Поэтому они должны совпасть, иначе сообщение как минимум получит минус в рейтинге, а в худшем случае будет отброшено.

В нашем примере за IP 1.2.3.4 должен быть закреплен server.example.org. DNS-запись выглядит так:

1.2.3.4.in-addr.arpa. IN PTR server.example.org

Для IPv6 используется ip6.arpa. В принципе, знать об особенностях PTR необязательно, так как PTR, за редким исключением, настраивает только хостинг-провайдер. И если оно не устраивает, то нужно просто обратиться в поддержку. Проверить PTR можно при помощи запроса:

$ dig -x 1.2.3.4

По факту PTR-запись после развертывания VDS может указывать на технический домен, представленный провайдером, вроде srv01.provider.net, в шаблоне VDS hostname вписан как Ubuntu1604 (меняется в /etc/hostname), в HELO/EHLO SMTP-сервер пишет вообще localhost.localdomain, а письмо идет от домена example.org. Вероятность доставки письма при таких условиях будет стремительно приближаться к нулю. Хотя некоторые сервисы отмечают подобные несоответствия как ошибку и проводят полную проверку.

Особо хочется обратить внимание, что VDS обычно имеет два IPv4 и v6. Поэтому все сказанное касается обеих версий, так как письмо к одному серверу может идти по IPv4 и доставляться, а другой предпочитает использовать IPv6, и письмо может не доходить до получателя. При этом очень много провайдеров, предоставляя IPv6, абсолютно не утруждают себя настройкой PTR-записи, и ее проверка возвращает ошибку. Но Google, например, предпочитает IPv6 и сразу отбрасывает письмо, если PTR не совпадает с именем сервера. В ответном сообщении сервиса это выглядит так:

Our system has detected that this message does
550-5.7.1 not meet IPv6 sending guidelines regarding PTR records and
550-5.7.1 authentication.

Как вариант — можно отключить IPv6 и отправлять только по IPv4. В /etc/postfix/main.cf Postfix для этого следует использовать всего одну строку:

inet_protocols = ipv4

После чего перезапустить сервис.

$ sudo service postfix restart

В Exim в /etc/exim/exim.conf

disable_ipv6 = true
Не забываем, что SMTP-сервер обычно использует IPv4 и IPv6
Не забываем, что SMTP-сервер обычно использует IPv4 и IPv6

Идеально, когда имя сервера в заголовке и адрес отправителя сообщения совпадают. Если планируется отслеживать свои рассылки через сервис postmaster.mail.ru, то другого варианта и нет. Там это требование проверяется жестко. Он поэтому и не видит рассылки с unisender.com и ему подобных, даже если домен закреплен и подтвержден. Просто потому, что в unisender.com используется собственный SMTP-сервер со своими заголовками и письмо идет не от example.org, а от

Received: from smtp26.emlone.com (smtp26.emlone.com [146.0.246.220])

То есть пишем провайдеру, чтобы поменял PTR на example.com, меняем hostname и проверяем, что сервер отвечает правильным HELO/EHLO. В Postfix за это ответственен параметр myorigin, указывающий имя домена, которое используется в почте, отправляемой с этой машины. По умолчанию myorigin = $myhostname, указывающее на имя хоста. Поэтому

myhostname = example.org

Иногда используется значение $mydomain, которое по умолчанию содержит доменную часть полного имени машины.

Exim в HELO/EHLO использует значение переменной primary_hostname, которая по умолчанию совпадает с именем хоста. Но можно задать его вручную:

primary_hostname = example.org

И здесь есть один нюанс, о котором нужно знать. Например, домен example.org прикреплен к Gmail, и вся работа с почтой ведется с этих аккаунтов. C VDS менеджеры на свой @example.org ящик должны получать только сообщения о заказе. Если настроить в SMTP-сервер EHLO example.org, то Google решит, что над ним явно издеваются, ведь домен у него даже не будет дальше проверять, просто отбросит сообщение.

Но если на одном VDS несколько доменов, то такая схема уже будет проблематичной. В принципе, в RFC нет явного запрета на несколько PTR-записей для одного IP, но есть уже устаревшая рекомендация IETF, в которой расписана эта проблема и совет не делать этого в первую очередь из-за возможных ошибок. Очевидно, его и придерживаются, во всяком случае, провайдеры не хотят добавлять еще PTR-записи. В такой ситуации нужно или оставить техническое имя сервера, или (лучше) выбрать один из используемых доменов как основной и настроить PTR и hostname под него.

 

Разбираемся с SPF

Изменить действующие технологии отправки почты, зародившиеся в восьмидесятых годах прошлого века, в глобальном масштабе уже невозможно. Это потребовало бы колоссальных затрат как времени, так и денег. Поэтому проблемы стали решать при помощи дополнений. Начало разработок Sender Policy Framework (SPF) датировано июнем 2003 года, в основе стоял Менг Венг Вонг (Meng Weng Wong) — основатель компании POBOX. Технология SPFv1 определена в RFC 4408 «Sender Policy Framework (SPF) for Authorizing Use of Domains in E-Mail, Version 1», опубликованном в апреле 2006 года, в 2014 году вышла новая версия — RFC 7208. Хотя крупные компании вроде Google, AOL, Amazon, eBay, W3C объявили о ее внедрении еще в 2004-м. Суть SPF проста: это нечто вроде персонального белого списка. Администратор почтового домена с помощью специальной TXT- или SPF-записи (опционально) в DNS-зоне перечисляет разрешенные адреса, с которых может отправляться почта. Сервер, получивший сообщение из этого домена, сверяет IP-адрес с SPF-записью. Если адрес указан в списке разрешенных, то считается, что проверка пройдена, и в сообщении появится новый заголовок Received-SPF: pass.

Несмотря на то что для SPF придуман отдельный тип записи, он так и остался опциональным (при наличии поля его лучше тоже создать, хуже не будет), TXT обязательна.

example.org TXT "v=spf1 a mx ip4:1.2.3.4 ~all"

Если домен может отправлять почту с нескольких адресов, все их прописываем здесь или указываем в MX-записи. Если VDS имеет IPv6-адрес, обязательно прописываем его здесь в ipv6:. Расшифруем:

  • v=spf1 — используемая версия SPF;
  • a — прием писем от узла с IP-адресом, указанным в A-записи домена;
  • mx — подключает адреса, указанные в MX-записях;
  • all — что делать с серверами, не перечисленными в SPF. Причем все указанное после all проверяться не будет, оно должно стоять последним.

Если ip4:1.2.3.4 есть в MX или A, его можно явно не прописывать и сократить запись до v=spf1 mx ~all. Можно подключать другие домены. Например, a:smtp.example.org разрешит сообщения с этого домена. Еще вариант — использовать параметр include, подключающий хосты, разрешенные SPF-записью указанного домена (например, include:_spf.yandex.net). Почти аналогичный параметр redirect перенаправляет проверку SPF на другой домен. Например, redirect:example.com. Администратор устанавливает политику SPF для домена:

  • None — означает, что в этом домене нет опубликованных SPF-записей, поэтому определить разрешения невозможно;
  • Neutral (?) — владелец домена явно указал, что он не хочет устанавливать разрешения, обрабатывается аналогично None и служит больше для информационных целей;
  • Pass (+) — прошедшему проверку разрешено отсылать сообщения. Установлен по умолчанию;
  • Fail (-) — клиент не уполномочен отсылать почту из этого домена, и принимающая сторона вправе пометить такое сообщение или отвергнуть. Например, v=spf1 -all указывает, что домен вообще не отправляет почту;
  • SoftFail (~) — отправитель не имеет права посылать сообщение, но принимающая сторона должна не отвергать сообщение, а провести дальнейшую проверку.

Fail и SoftFail обычно используются в all. То есть при -all все сообщения, не попадающие под правила, следует однозначно отвергать.

Проверить SPF-запись можно при помощи онлайн-сервисов SPF Record Testing Tools, mxtoolbox.com или утилиты spfquery.

$ apt install spfquery
$ spfquery -ip=1.2.3.4 -sender=mail@example.org -helo=example.org

В 2004 году в MS предложили схожую с SPF технологию, названную Sender ID и использующую DNS-записи spf2.0/pra, или spf2.0/mfrom, или spf2.0/mfrom,pra. Проверяется MAIL FROM, а не адрес возврата. Технология в настоящее время не получила широкого распространения, и MS рекомендует при отсутствии явных записей spf2.0 рассматривать v=spf1 как эквивалент spf2.0/mfrom,pra и использовать его при анализе. Вот, собственно, и все, что нужно о ней знать.

В принципе, если выполнить все рекомендации, можно уже смело отправлять письма, застревать они не должны. Но некоторые сервисы требуют обязательного подписывания сообщений.

Проверяем SPF
Проверяем SPF
 

Настраиваем DKIM

В основу DKIM (DomainKeys Identified Mail) легли две разработки — технология DomainKeys от Yahoo и система Internet Identified Mail от Cisco. Новый проект был подан на утверждение в качестве стандарта IETF в 2005 году. Принцип DKIM очень прост. Каждое сообщение снабжается цифровой подписью, которая удостоверяет отправителя и гарантирует, что подписанная часть не изменялась. Сам процесс напоминает работу любой системы с открытым ключом. Владелец домена создает пару ключей — открытый и приватный. Приватный используется на SMTP-сервере для подписи сообщения, которая передается в заголовке DKIM-Signature. Домен указывается в поле d=, список подписанных заголовков перечисляется в ключе h:

h=From:Subject:Reply-To:List-Unsubscribe:To:Message-Id:Date:MIME-Version:Content-Type; i=info@example.org;

Открытый ключ добавляется в TXT-поле DNS-записи и при поступлении письма запрашивается получателем, который проверяет, действительно ли подпись была сгенерирована для домена, указанного в адресе отправителя. При положительном результате в сообщении появляется подзаголовок Authentication-Results: dkim=pass.

Если принимающая сторона не умеет проверять подпись, то на прохождении сообщения это никак не сказывается. Также нужно отметить, что правильный DKIM обычно не служит для антиспам-систем указанием на дальнейшее прохождение проверок. Но по опыту его наличие обычно поднимает его рейтинг насколько, что он редко застревает в фильтрах. Некоторые сервисы вроде postmaster.mail.ru требуют обязательного наличия подписанных DKIM-сообщений в привязанном домене, иначе статистика показываться не будет.

DKIM подписывают сообщения основные почтовые сервисы, и если привязать домен к Яндексу или Google, выполнив все инструкции, то больше ничего делать не нужно. Яндекс подключает DKIM обычно не сразу, а через день-два.

Настроим Postfix, чтобы он подписывал сообщения. Будем считать, что он установлен и сконфигурирован. Далее нам понадобится пакет OpenDKIM.

$ sudo apt install opendkim opendkim-tools

Демон будет работать с правами opendkim:opendkim. Генерируем ключи для селектора mail.

$ sudo mkdir -p /etc/mail/example.org
$ cd /etc/mail/example.org
$ sudo opendkim-genkey -s mail -d example.org

В текущем каталоге появятся два файла: mail.private — закрытый ключ и mail.txt — открытый. Добавляем в DNS-запись типа TXT из mail.txt.

mail._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCS....ViwIDAQAB"

Настройки OpenDKIM в Ubuntu находятся в файле /etc/opendkim.conf. Их, в принципе, может быть много, и могут использоваться дополнительные файлы, так как один демон часто обслуживает несколько доменов. В /usr/share/doc/opendkim/examples есть пример. Но в простом случае достаточно изменить несколько параметров под свои условия.

Domain    example.org
KeyFile    /etc/mail/example.org/mail.private
Selector    mail
# По умолчанию подпись только проверяется, нужно изменить на sv (signer, verifier)
Mode sv

После установки демон opendkim слушает сокет /var/run/opendkim/opendkim.sock, но при необходимости можно указать сетевой порт и интерфейс. После правки файла перезапускаем демон:

$ sudo service opendkim restart

Добавляем в /etc/postfix/main.cf данные сокета:

milter_default_action = accept
milter_protocol = 2
smtpd_milters = /var/run/opendkim/opendkim.sock
non_smtpd_milters = /var/run/opendkim/opendkim.sock

$ sudo service postfix restart

Коротко это все настройки.

Проверить DKIM можно с помощью утилиты opendkim-testkey:

$ opendkim-testkey -d example.org -s mail -vvv
Настройки в /etc/opendkim.conf
Настройки в /etc/opendkim.conf

Мир быстро меняется, VDS переносятся на другой IP. Но антиспам-технологии, в частности SPF и DKIM, не совсем четко указывают, что делать при несоответствии правилам, например письмо проходит только DKIM или только SPF. Кроме того, владелец домена не знает, если с его адресов происходит рассылка. Эти проблемы призвана решить технология DMARC (Domain-based Message Authentication, Reporting, and Conformance, описана в RFC 7489), указывающая, как проверять почту домена. DMARC тоже прописывается в виде DNS-записи. Обязательны поля v (версия) и p (политика). Как минимум можно собирать статистику по неправильным сообщениям:

_dmarc.example.org TXT "v=DMARC1; p=none; rua=mailto:mail@example.org"

Доступны три варианта политик:

  • none — без рекомендаций, регистрировать сообщения, не прошедшие проверку (отчет отсылается по адресу, указанному в rua);
  • quarantine — помечать как спам;
  • reject — отклонить сообщение.

Собственно, в указанном примере и вся суть DMARC. Остальные параметры доступны в RFC.

 

Если письмо не доставляется

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

Способ обращения в службу поддержки у разных сервисов отличается, найти их на сайте не всегда просто.

В Яндекс нужно заполнить форму в конце страницы, выбрав причину обращения. В Mail.Ru есть специальный ящик abuse@corp.mail.ru. Но лучше отослать сообщение через веб-форму при блокировке писем, если письмо попадает в спам.

У Google нет поддержки бесплатных продуктов, в том числе и почты Gmail. Но те, кто занимается рассылками, могут отправить запрос через специальную форму. Может, повезет и тебе ответят. Там же есть ссылки на документацию.

У Рамблера формы нет, проблемы нужно отсылать на abuse@rambler-co.ru.

 

Заключение

Вот и все! Если проделать все описанное, то о проблемах с доставкой почты можно забыть.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    3 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии