Сайту почта нужна почти всегда: формы обратной связи, регистрация, восстановление пароля, уведомления магазину. При этом «полный» почтовый сервер с ящиками сотрудников — отдельная история. Для веб-сайта чаще всего хватает надёжной исходящей отправки через Postfix. В этой статье покажу практичную схему под сайт (часто WordPress) и типичные грабли, из‑за которых письма уходят в спам или не уходят вовсе.
Если вам нужны виртуальные ящики для людей — смотрите отдельную заметку про Postfix + Dovecot. Здесь фокус именно на сайте.
Что обычно нужно сайту
- Отправлять письма
From: noreply@example.comили с адреса домена сайта. - Не принимать чужую почту с интернета (не стать open relay).
- Чтобы PHP / WordPress могли отдать письмо локально (sendmail) или по SMTP на
127.0.0.1:25. - Чтобы принимающие сервера (Gmail, Яндекс, корпоративная почта) хоть как‑то доверяли отправителю.
Понятно, что «поставил Postfix и забыл» почти не бывает. Без PTR, SPF и нормального From письма будут тонуть. Про доставляемость связкой SPF + DKIM + DMARC я уже писал отдельно — к ней вернёмся в конце как к обязательному следующему шагу.
Итак, теории достаточно. Начнём.
Два рабочих сценария
1. Сайт шлёт сам через локальный Postfix
Сервер сайта = исходящий MTA. Postfix слушает только localhost, наружу отдаёт письма сам. Это простой и предсказуемый вариант для одного VPS с одним‑двумя сайтами.
2. Сайт отдаёт письма на внешний SMTP (relayhost)
Локальный Postfix — «тонкий клиент»: принимает от PHP и пересылает на SendGrid / Amazon SES / корпоративный SMTP / отдельный почтовый VPS. Удобно, если IP сайта «грязный» или провайдер режет 25 порт.
Дальше разберу первый сценарий подробнее, а для второго покажу ключевые строки relayhost.
Установка Postfix (Ubuntu)
sudo apt update
sudo apt install postfix mailutils
В инсталляторе тип конфигурации удобнее выбрать Internet Site, если сервер сам будет доставлять наружу, или Satellite system, если весь исходящий поток уходит на relay. System mail name — ваш домен, например example.com.
Проверка, что сервис жив:
systemctl status postfix
postconf mail_version
Базовая конфигурация «под сайт, без открытого релэя»
Правим /etc/postfix/main.cf (значения подставьте свои). Идея простая: снаружи на 25 порт нас лучше не слушать, локально PHP должен достучаться.
# Имя хоста, с которым Postfix представляется миру
myhostname = mail.example.com
# Домен для неполных адресов
myorigin = /etc/mailname
# Что считаем «своим» для локальной доставки.
# Для чисто исходящего сайта часто достаточно localhost.
mydestination = localhost.$mydomain, localhost
# Сети, которым разрешено релэить через нас
mynetworks = 127.0.0.0/8 [::1]/128
# Не слушаем внешний мир на SMTP — только локально
inet_interfaces = loopback-only
inet_protocols = ipv4
# Баннер и формат
smtpd_banner = $myhostname ESMTP
append_dot_mydomain = no
После правок:
sudo postfix check
sudo systemctl reload postfix
Важно: если оставить inet_interfaces = all и ослабить ограничения, легко получить open relay. Для веб‑сайта loopback‑only — самый безопасный дефолт. Принимать почту на MX в этой схеме мы и не планируем.
DNS, которые должны быть до запуска «в прод»
- A для
mail.example.com→ IP сервера сайта (или почтового хоста). - PTR (обратная зона) IP → тот же
mail.example.com. Без PTR у многих провайдеров письма режутся сразу. PTR обычно заказывается у хостера по тикету. - SPF TXT на домене, если с этого IP реально уходит почта, например:
v=spf1 ip4:YOUR_IP ~all.
MX для исходящего‑only сайта формально не обязателен. Но если на домене вообще нет MX, часть фильтров смотрит косо. Часто ставят MX на нормальный ящик (Google Workspace / Яндекс / отдельный почтовый сервер), а сайт шлёт с того же домена через SPF ip4: сервера сайта. Главное — не плодить несколько SPF‑записей.
Как WordPress и PHP отдают письма в Postfix
По умолчанию wp_mail() в WordPress идёт через PHP mail(), а та на Linux обычно зовёт sendmail‑совместимый бинарник Postfix (/usr/sbin/sendmail). Если Postfix локально работает — формы и системные письма WordPress уже могут уходить без SMTP‑плагина.
Быстрая проверка с сервера:
echo "Test body" | mail -s "Postfix test" you@example.com
# смотрим очередь и логи
mailq
sudo tail -n 50 /var/log/mail.log
# на некоторых системах:
# sudo journalctl -u postfix -n 50 --no-pager
Если хотите явно SMTP на localhost (плагины вроде WP Mail SMTP / FluentSMTP), хост 127.0.0.1, порт 25, без шифрования на loopback — нормальная схема. Не публикуйте этот порт наружу «для удобства».
Отдельный момент: From должен совпадать с доменом, который вы авторизуете в SPF/DKIM. Письма From: wordpress@localhost или с чужого gmail «через ваш IP» — классический путь в спам. В WordPress задайте нормальный From в настройках плагина SMTP или маленьким сниппетом на фильтры wp_mail_from / wp_mail_from_name.
Вариант с relayhost (если 25 порт закрыт или IP плохой)
relayhost = [smtp.provider.example]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_use_tls = yes
Файл паролей:
# /etc/postfix/sasl_passwd
[smtp.provider.example]:587 username:password
sudo postmap /etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo systemctl reload postfix
В SPF тогда должен быть механизм провайдера (include:), а не только IP сайта — иначе DKIM/SPF разъедутся с реальностью.
TLS для исходящих соединений
Даже если SMTP снаружи не слушаете, Postfix всё равно ходит на чужие MX. Имеет смысл включить клиентский TLS. Подробный разбор STARTTLS/сертификатов — в статье Postfix TLS/STARTTLS. Минимально часто ставят:
smtp_tls_security_level = may
smtp_tls_loglevel = 1
may — шифруем, если принимающая сторона умеет; не роняем доставку там, где TLS ещё кривой. Для параноидальных контуров уже смотрят encrypt и политики по доменам.
Типичные ошибки именно у сайт‑почты
- Сайт шлёт с одного IP, а SPF описывает другой — получатель ставит fail. Смотрите реальный исходящий IP в логах и в заголовках письма.
- Форма подставляет From = email посетителя. Так делать нельзя, это и спуфинг, и поломка SPF. From — ваш домен, а адрес пользователя — в
Reply-To. - Очередь растёт, а в логах defer — серый список, временный reject, нет PTR, блок 25 порта.
mailqиmail.log— первые друзья. - Open relay «на всякий случай» — через сутки станете частью чужого спама, IP улетит в чёрные списки. Не делайте так
- Сразу жёсткий DMARC — сначала observe, потом quarantine/reject. Об этом тоже в гайде по SPF/DKIM/DMARC.
Как проверить, что всё работает
- Отправьте тестовое письмо на свою почту на Gmail/Яндекс с сервера и с формы сайта.
- Откройте «исходник письма» и проверьте
Received, наличие нормального From, при наличии DKIM — заголовок подписи. - Посмотрите
Authentication-Results: желательноspf=pass, позжеdkim=pass. - Прогоните домен через MX Toolbox / mail-tester.com — не как истину в последней инстанции, а как быстрый чеклист.
- Убедитесь, что с внешней сети
telnet YOUR_IP 25не открывается, если выбран режим loopback‑only.
Что делать дальше
Когда базовая отправка с сайта заработала, следующим слоем я бы ставил:
- DKIM для Postfix и выравнивание с DMARC;
- полноценную связку SPF + DKIM + DMARC.
Для веб‑сайта Postfix в режиме «только исходящие с localhost» — достаточный и надёжный фундамент. Главное не смешивать в одной голове «формы WordPress» и «корпоративную почту на 50 ящиков» без необходимости, это разные задачи и разный объём сопровождения.