Каждый раз поднимая новый сервер в облаках, вы получаете случайный IP-адрес. Не все понимают, что IP-адрес может попасть к вам с "историей". Часто приходится тратить время на удаление IP из публичных черных списков. В моём случае в последний раз это была очень неторопливая переписка с mail.ru, которая ни к чему не привела. После этого, создав новый сервер, я задумался: как же сделать так, чтобы не огребать проблем с такими IP-адресами?
Введение
Несмотря на то, что серверы у меня могут быть как постоянные так и "на поиграться", почту на всех них я не обслуживаю, но очень хочу получать сервисные письма от своих скриптов и системных служб.
Очевидное решение — сделать свой "порядочный" почтовый шлюз и все остальные серверы настраивать на пересылку почты через этот шлюз. Минусы такого решения очевидны:
- Отдельный сервер стоит денег, даже если это дешевая VPSка
- IP-адрес надо постоянно отслеживать в черных списках
- Настройка почтового шлюза требует времени, которое зависит от ваших скиллов
Из-за вышеперечисленных причин я пошёл искать другое решение, и, что характерно, нашёл.
Решение
Я обнаружил возможность схалявить, воспользовавшись сервисом "Почта для Домена" от Yandex. На тот момент у меня было поднято 3 сервера и в DNS были следующие А-записи:
Хост | Тип | Значение |
---|---|---|
example.com | A | 123.123.123.120 |
server1.example.com | A | 123.123.123.121 |
server2.example.com | A | 123.123.123.122 |
server3.example.com | A | 123.123.123.123 |
Я зарегистрировал свой технический домен в "Почте для Домена" и создал аккаунт: root@example.com
. Попробовал отправить письма с одного из своих серверов, используя этот SMTP-аккаунт и получил следующую ошибку:
553 5.7.1 Sender address rejected: not owned by auth user.
envelope from address root@server1.example.com not accepted by the server
Yandex не разрешает подставлять какие попало данные в envelope-from
. Но как же быть, если хочется понимать, с какого сервера пришло то или иное письмо, без дополнительных ухищрений?
Чтобы соблюсти правила Yandex'a, нужно выполнить следующие шаги на стороне их сервиса:
Зарегистрировать основной домен и его поддомены в pdd.yandex.ru. Проще всего пройти подтверждение домена через добавление CNAME-записи:
Хост Тип Значение example.com CNAME verification-code server1.example.com CNAME verification-code server2.example.com CNAME verification-code server3.example.com CNAME verification-code
Так же для каждого домена создаем MX-запись:
Хост Тип Приоритет Значение example.com MX 10 mx.yandex.ru server1.example.com MX 10 mx.yandex.ru server2.example.com MX 10 mx.yandex.ru server3.example.com MX 10 mx.yandex.ru
В настройках основного домена указать поддомены как алиасы этого домена.
Создаём почтовый аккаунт
root@example.com
, если он ещё не создан
- Обязательно нужно зайти в аккаунт через веб-интерфейc и активировать его, иначе получите ошибку:
535 5.7.8 Error: authentication failed: Please accept EULA first. https://mail.yandex.ru/for/example.com
Дальше требуется работа на нашей стороне — настраиваем сервера:
- Устанавливаем
msmtp
— миниатюрный SMTP-клиент, который предоставляет свою реализациюsendmail
Настраиваем его:
defaults syslog LOG_MAIL tls_certcheck off tls on auto_from on # server hostname maildomain server1.example.com account default host smtp.yandex.ru port 25 auth on user root@example.com password 123qwe
- Отправляем тестовое письмо с отладкой:
echo -e "test message" | /usr/bin/msmtp --debug -t -i sugdyzhekov@plesk.com
и смотрим результат:
loaded system configuration file /etc/msmtprc ignoring user configuration file /root/.msmtprc: No such file or directory falling back to default account using account default from /etc/msmtprc host = smtp.yandex.ru port = 25 proxy host = (not set) proxy port = 0 timeout = off protocol = smtp domain = localhost auth = choose user = root@example.com password = * ntlmdomain = (not set) tls = on tls_starttls = on tls_trust_file = (not set) tls_crl_file = (not set) tls_fingerprint = (not set) tls_key_file = (not set) tls_cert_file = (not set) tls_certcheck = off tls_min_dh_prime_bits = (not set) tls_priorities = (not set) auto_from = on maildomain = server1.example.com from = root@server1.example.com add_missing_from_header = on add_missing_date_header = on remove_bcc_headers = on dsn_notify = (not set) dsn_return = (not set) logfile = (not set) syslog = LOG_MAIL aliases = (not set) reading recipients from the command line and the mail <-- 220 smtp3h.mail.yandex.net ESMTP (Want to use Yandex.Mail for your domain? Visit http://pdd.yandex.ru) --> EHLO localhost <-- 250-smtp3h.mail.yandex.net <-- 250-8BITMIME <-- 250-PIPELINING <-- 250-SIZE 42991616 <-- 250-STARTTLS <-- 250-AUTH LOGIN PLAIN XOAUTH2 <-- 250-DSN <-- 250 ENHANCEDSTATUSCODES --> STARTTLS <-- 220 Go ahead TLS certificate information: Owner: Common Name: smtp.yandex.ru Organization: Yandex LLC Organizational unit: ITO Locality: Moscow State or Province: Russian Federation Country: RU Issuer: Common Name: Yandex CA Organization: Yandex LLC Organizational unit: Yandex Certification Authority Country: RU Validity: Activation time: Mon 12 Oct 2015 03:41:24 PM MSK Expiration time: Wed 11 Oct 2017 03:41:24 PM MSK Fingerprints: SHA1: B7:0E:62:55:E1:3A:C0:F3:08:12:35:B2:9D:4B:25:D0:B8:C1:C6:39 MD5: BC:15:CE:B6:D4:FF:0D:95:4F:E5:1A:A7:3A:DF:DA:65 --> EHLO localhost <-- 250-smtp3h.mail.yandex.net <-- 250-8BITMIME <-- 250-PIPELINING <-- 250-SIZE 42991616 <-- 250-AUTH LOGIN PLAIN XOAUTH2 <-- 250-DSN <-- 250 ENHANCEDSTATUSCODES --> AUTH PLAIN AhJvb3ARY29uzMlntS5ydQBXYw5VcMMlazk= <-- 235 2.7.0 Authentication successful. --> MAIL FROM:<root@server1.example.com> --> RCPT TO:<sugdyzhekov@plesk.com> --> DATA <-- 250 2.1.0 <root@server1.example.com> ok <-- 250 2.1.5 <sugdyzhekov@plesk.com> recipient ok <-- 354 Enter mail, end with "." on a line by itself --> From: root@server1.example.com --> Date: Mon, 06 Jun 2016 16:17:00 +0300 --> test message --> . <-- 250 2.0.0 Ok: queued on smtp3h.mail.yandex.net as 1465219021-86hlZkGCpZ-H0J8ORE2 --> QUIT <-- 221 2.0.0 Closing connection.
Отлично, успех! Письмо ушло, правда, найдем мы его в спаме, так как оно почему-то пустое. Давайте проверим более привычным и "человеческим" способом:
echo "test message" | mailx -s 'test subject' sugdyzhekov@plesk.com
Вот, теперь в ящике нормальное письмо. Здорово!
DKIM & SPF
А еще можно для каждого домена прописать записи DKIM и SPF. Если вы, как я, используете свой DNS-хостинг, то просто скопируйте соответствующие значения из “DNS редактора” в интерфейсе Яндекса. Внимание: для каждого домена и алиаса свой ключ!
Хост Тип Значение mail._domainkey.example.com TXT v=DKIM1; k=rsa; t=s; p=MIGf... mail._domainkey.server1.example.com TXT v=DKIM1; k=rsa; t=s; p=MIGf... mail._domainkey.server2.example.com TXT v=DKIM1; k=rsa; t=s; p=MIGf... mail._domainkey.server3.example.com TXT v=DKIM1; k=rsa; t=s; p=MIGf...
Отсылаем с сервера письмо и смотрим в заголовки:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=mail; t=1467009762; bh=Pb6s/Xlf4... Authentication-Results: smtp14.mail.yandex.net; dkim=pass header.i=@example.com
Лепота!
В случае если отправка почты для домена будет происходить только через сервера Яндекс и с заранее известных IP-адресов, то можно смело прописать SPF-записи в соответствии с документацией https://yandex.ru/support/pdd/troubleshooting/dns.xml#step2
Хост Тип Значение example.com TXT v=spf1 redirect=_spf.yandex.net server1.example.com TXT v=spf1 redirect=_spf.yandex.net server2.example.com TXT v=spf1 redirect=_spf.yandex.net server3.example.com TXT v=spf1 redirect=_spf.yandex.net
Нюансы
Скорее всего, вы молодцы, и ваше приложение работает не из под root'а. Попытка послать письмо из-под обычного пользователя опять приведёт к знакомой ошибке в логе msmtp:
Jun 6 14:21:24 server1 msmtp: host=smtp.yandex.ru tls=on auth=on user=root@example.com from=app@server1.example.com recipients=sugdyzhekov@plesk.com smtpstatus=553 smtpmsg='553 5.7.1 Sender address rejected: not owned by auth user.' errormsg='envelope from address user@server1.example.com not accepted by the server' exitcode=EX_DATAERR
Можно решить эту проблему по-разному. Например, можно явно указывать пользователя, отключив опцию
auto_from off
вmsmtp
. Но я уже решил, что меня это не устраивает.
Правильное решение — добавить пользователя как алиас для нашего основного адреса:
Локальный релей
Если вам требуется локальный SMTP-релей, то данная конфигурация вам тоже подходит. Нужно просто заменить msmtp на postfix или exim, настроенные на использование серверов Яндекса в качестве smart host'a (гуглить можно, например, по ключевым словам exim smarthost).
Резюме
Теперь любой сервер, который я поднимаю для своих задачек, сразу же получает настроенный канал отправки почты. В DNS и pdd.yandex.ru я заранее прописал несколько поддоменов про запас. Так как сервера я разворачиваю через SaltStack, то конфигурацию msmtp мои сервера получают автоматически.
Что я получил в итоге:
- Самое главное — нет заморочек с черными списками и IP-адресами серверов, так как письма уходят через сервера Яндекса
- DKIM/SPF "из коробки" — письма не попадают в спам
- msmtp простой SMTP-клиент, которому даже в памяти сервера висеть не нужно — запускается по необходимости
- msmtp — простейшая настройка в отличие от "взрослых" postfix, exim
- можно не беспокоиться о PTR-записях для ваших IP-адресов с точки зрения почтовой системы.
Надеюсь эта инструкция кому-нибудь пригодится. Буду рад узнать из комментариев, кто и как решает подобную проблему.