Письма с сайта — заявки, подтверждение подписки, сброс пароля — должны доходить и не попадать в спам. Самый очевидный путь, поднять почтовый сервер рядом с сайтом, почти гарантированно ведёт в спам. Как сделано здесь: свой сервер почты не поднимаем, а отправляем через ящик на домене у почтового провайдера.
Это восьмая часть цикла «Сервер для WordPress».
Почему не свой почтовый сервер
- адрес сервера. Домашние и многие облачные адреса заранее числятся в списках, откуда почту не принимают или сразу кладут в спам. Сайт этот работает на домашнем сервере — отправлять с него напрямую бессмысленно;
- репутация. У нового почтового сервера её нет, и крупные почтовые службы относятся к нему с подозрением месяцами;
- обслуживание. Свой почтовый сервер — это ещё один сервис, за которым надо следить.
Почта домена уже живёт у хостинг-провайдера, где куплен домен: там записи MX и SPF, там ящики. Сайт просто отправляет письма через SMTP этого провайдера, как обычный почтовый клиент.
Как подключено
В нашем образе PHP есть msmtp — маленький SMTP-клиент, который подменяет sendmail. Его конфиг собирается при старте контейнера из переменных окружения:
php:
environment:
SMTP_HOST: ${SMTP_HOST:-} # пусто — почта не настраивается вовсе
SMTP_PORT: ${SMTP_PORT:-465}
SMTP_FROM: ${SMTP_FROM:-}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_TLS: true
SMTP_TLS_CERTCHECK: true
Сами значения — в файле .env рядом с compose, с правами 600. Отдельный ящик noreply@ на домене только для отправки с сайта.
Грабля шаблона. В исходном compose, с которого начинался сайт, адрес SMTP-сервера был вписан жёстко — от другого проекта. Сайт пытался отправлять почту через чужой сервер. Все параметры почты — только из .env конкретного сайта.
Пароль со спецсимволами (! * &) в .env — в одинарных кавычках, иначе его часть съест подстановка. Смена пароля — правка .env и пересоздание контейнера PHP.
Отправитель — только свой адрес
WordPress по умолчанию отправляет служебные письма от wordpress@домен. SMTP провайдера такое письмо не примет: отправлять можно только от имени ящика, под которым вошли. Поэтому все письма сайта уходят от своего ящика:
add_filter('wp_mail_from', function ($email) {
$from = theme_option('emailfrom'); // noreply@домен
return $from !== '' && is_email($from) && strpos($email, 'wordpress@') === 0 ? $from : $email;
});
add_filter('wp_mail_from_name', function ($name) {
return $name === 'WordPress' ? get_bloginfo('name') : $name;
});
Ответить клиенту — одной кнопкой
Заявка приходит от noreply@, и «Ответить» в почтовике ушло бы в никуда. Если посетитель оставил почту в поле «контакт», она ставится в Reply-To — ответ уходит сразу ему.
Проверка
- письмо доходит и не в спаме — проверено на реальном ящике получателя;
- отказ отправки виден: у заявок в админке есть колонка «Доставка» с текстом ошибки (как это сделано);
- выход на порты 465 и 587 с сервера открыт — без этого не поможет ни одна настройка.
Письма с сайта уходят в спам или не приходят?
Пришлите адрес — настрою отправку через ящик на вашем домене и проверю доставку.
// загружаю комментарии…