Письма о новых комментариях, сбросе пароля или заказах WooCommerce не доходят до адресата? Это одна из самых частых проблем WordPress. Причина проста: функция wp_mail() по умолчанию использует PHP-функцию mail(), которая отправляет письма напрямую с сервера. Большинство почтовых провайдеров (Gmail, Outlook, Яндекс) считают такие письма подозрительными, потому что у shared-хостинга нет репутации отправителя, а SPF/DKIM-записи отсутствуют или настроены неверно.
Решение — использовать настоящий SMTP-сервис вроде Mailgun или SendGrid. Они принимают письма через защищённый канал с авторизацией, подписывают их DKIM и доставляют во «Входящие», а не в спам. При этом устанавливать плагин WP Mail SMTP (который добавляет 3 МБ кода и делает лишние запросы к базе данных) необязательно. Достаточно 20 строк кода в functions.php.
Почему не стоит использовать wp_mail() на продакшне
- Нет аутентификации: письмо отправляется от имени
www-data@server.hostname, что выглядит как спам - IP хостинга в блэклистах: на shared-хостинге сотни сайтов делят один IP; если один из них рассылал спам, ваш IP уже заблокирован
- Нет обратной связи:
mail()возвращаетtrueдаже если письмо не дошло — вы не узнаете о проблеме - Ограничения хостера: многие хостинги (включая Бегет) лимитируют количество писем в час или полностью блокируют
mail()
Шаг 1: Выбор почтового сервиса
Два наиболее надёжных варианта для WordPress:
| Сервис | Бесплатный тариф | Протокол | Особенности |
|---|---|---|---|
| Mailgun | 100 писем/день (Flex) | SMTP / API | Отличная документация, быстрая доставка, удобные логи |
| SendGrid | 100 писем/день | SMTP / API | Принадлежит Twilio, хорошая интеграция, аналитика открытий |
Оба сервиса поддерживают SMTP-протокол, что позволяет подключить их через стандартные хуки WordPress без дополнительных библиотек. Для небольших блогов и магазинов бесплатного тарифа достаточно.
Шаг 2: Регистрация и получение SMTP-данных
Для Mailgun:
- Зарегистрируйтесь на mailgun.com
- Создайте новый домен (например,
mg.custom-code.ru) - Добавьте DNS-записи (TXT для SPF/DKIM, MX для входящих) — Mailgun покажет точные значения
- Перейдите в Sending → Domains → выберите домен → SMTP credentials
- Скопируйте: SMTP hostname (
smtp.mailgun.org), порт (587), логин (postmaster@mg.custom-code.ru) и пароль
Для SendGrid:
- Зарегистрируйтесь на sendgrid.com
- Перейдите в Settings → Sender Authentication → Verify Your Single Sender Identity
- Подтвердите email отправителя
- Перейдите в Settings → API Keys → Create API Key → выберите Full Access или Restricted Access (Mail Send)
- Скопируйте API-ключ (он начинается с
SG.)
Шаг 3: Подключение SMTP через functions.php
WordPress предоставляет хук phpmailer_init, который позволяет перехватить объект PHPMailer до отправки письма и заменить настройки. Никаких плагинов не нужно.
Вариант А: Mailgun через SMTP
add_action( 'phpmailer_init', function( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = 'smtp.mailgun.org';
$phpmailer->Port = 587;
$phpmailer->SMTPAuth = true;
$phpmailer->Username = 'postmaster@mg.custom-code.ru';
$phpmailer->Password = 'your-mailgun-password';
$phpmailer->SMTPSecure = 'tls';
$phpmailer->From = 'noreply@custom-code.ru';
$phpmailer->FromName = 'Custom Code';
} );Вариант Б: SendGrid через SMTP
add_action( 'phpmailer_init', function( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = 'smtp.sendgrid.net';
$phpmailer->Port = 587;
$phpmailer->SMTPAuth = true;
$phpmailer->Username = 'apikey'; // Всегда "apikey" для SendGrid
$phpmailer->Password = 'SG.xxxxxxxxxxxxxxxxxxxxxxxx'; // Ваш API-ключ
$phpmailer->SMTPSecure = 'tls';
$phpmailer->From = 'noreply@custom-code.ru';
$phpmailer->FromName = 'Custom Code';
} );⚠️ Важно: Не храните пароли и API-ключи прямо в коде. Используйте константы в wp-config.php:
// В wp-config.php
define( 'CUSTOMCODE_SMTP_USER', 'postmaster@mg.custom-code.ru' );
define( 'CUSTOMCODE_SMTP_PASS', 'your-password-here' );
// В functions.php
$phpmailer->Username = CUSTOMCODE_SMTP_USER;
$phpmailer->Password = CUSTOMCODE_SMTP_PASS;Шаг 4: Настройка DNS-записей (SPF, DKIM, DMARC)
Без правильных DNS-записей даже SMTP-сервис не гарантирует доставку во «Входящие». Эти записи подтверждают, что Mailgun/SendGrid имеет право отправлять письма от вашего домена.
SPF (Sender Policy Framework)
Указывает, какие серверы могут отправлять почту от вашего домена:
# Для Mailgun
v=spf1 include:mailgun.org ~all
# Для SendGrid
v=spf1 include:sendgrid.net ~all
# Если используется и хостинг, и сервис
v=spf1 include:mailgun.org include:_spf.beget.com ~allТип записи: TXT, имя: @ (или пустое).
DKIM (DomainKeys Identified Mail)
Цифровая подпись каждого письма. Mailgun и SendGrid генерируют DKIM-ключ при добавлении домена. Скопируйте значение из панели сервиса и добавьте как TXT-запись:
# Пример для Mailgun
Имя: mailo._domainkey
Значение: k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBg...DMARC
Политика обработки писем, не прошедших SPF/DKIM:
Имя: _dmarc
Значение: v=DMARC1; p=quarantine; rua=mailto:dmarc@custom-code.ru; pct=100p=quarantine означает, что непроверенные письма попадают в спам. После подтверждения стабильной доставки можно изменить на p=reject.
Шаг 5: Тестирование доставки
После настройки обязательно проверьте, что письма доходят корректно.
Тестовое письмо через WP-CLI:
wp eval 'wp_mail("test@example.com", "SMTP Test", "Если вы получили это письмо, SMTP настроен правильно.");'Что проверить:
- Доставка: письмо пришло во «Входящие», а не в спам
- Заголовки: откройте исходный код письма и найдите
Authentication-Results— SPF и DKIM должны бытьpass - Отправитель: поле From должно показывать
noreply@custom-code.ru, а неwww-data@server
Проверка через сервисы:
Отправьте тестовое письмо на mail-tester.com — он покажет оценку от 0 до 10 и детальный разбор каждой проблемы. Цель — получить 9/10 или 10/10.
Шаг 6: Логирование ошибок отправки
По умолчанию WordPress молча игнорирует ошибки SMTP. Добавляем логирование, чтобы знать о проблемах:
add_action( 'phpmailer_init', function( $phpmailer ) {
// ... настройки SMTP из Шага 3 ...
// Включаем детальное логирование при ошибке
$phpmailer->SMTPDebug = 0; // 0 = выкл, 1 = клиент, 2 = клиент+сервер
} );
// Логируем неудачные отправки
add_action( 'wp_mail_failed', function( $wp_error ) {
error_log( '[WP Mail Failed] ' . $wp_error->get_error_message() .
' | To: ' . implode(', ', $wp_error->get_error_data()['to'] ?? [] ) );
} );Логи пишутся в /var/log/php-fpm/error.log или в wp-content/debug.log (если включён WP_DEBUG_LOG). На Бегете проверяйте раздел «Логи» в панели управления.
Шаг 7: Отключение плагинов SMTP
Если ранее использовались плагины WP Mail SMTP, Easy WP SMTP или Post SMTP — деактивируйте их, чтобы избежать конфликтов:
wp plugin deactivate wp-mail-smtp easy-wp-smtp post-smtpНаш код в functions.php полностью заменяет их функциональность, работая быстрее и без лишних запросов к базе данных.
Решение частых проблем
Ошибка «SMTP connect() failed»
Чаще всего причина в одном из трёх:
- Неверный порт: используйте 587 для TLS или 465 для SSL. Порт 25 часто заблокирован хостером
- Хостинг блокирует исходящие SMTP: на некоторых тарифах Бегет блокирует внешние SMTP-соединения. Проверьте через поддержку или попробуйте порт 2525 (альтернативный порт Mailgun)
- Неверные учётные данные: для SendGrid логин всегда
apikey, а пароль — сам API-ключ, а не пароль от аккаунта
Письма уходят, но попадают в спам
Проверьте три вещи:
- DNS-записи SPF/DKIM/DMARC настроены и валидны (проверьте через mail-tester.com)
- Домен отправителя (
From) совпадает с верифицированным доменом в Mailgun/SendGrid - Репутация домена не испорчена предыдущими рассылками (проверьте через Google Postmaster Tools)
Письма отправляются слишком медленно
SMTP-соединение устанавливается синхронно — пользователь ждёт завершения отправки. Решения:
- Используйте Action Scheduler для фоновой отправки писем (разбирали в статье про Action Scheduler)
- Переключитесь на API-метод вместо SMTP (Mailgun/SendGrid HTTP API работает в 3-5 раз быстрее SMTP)
Как переключиться на API вместо SMTP?
API-метод быстрее и надёжнее, но требует библиотеку Guzzle или использование wp_remote_post(). Пример для Mailgun:
add_filter( 'wp_mail', function( $args ) {
// Перехватываем wp_mail и отправляем через Mailgun API
$response = wp_remote_post( 'https://api.mailgun.net/v3/mg.custom-code.ru/messages', [
'headers' => [
'Authorization' => 'Basic ' . base64_encode( 'api:' . CUSTOMCODE_MAILGUN_API_KEY ),
],
'body' => [
'from' => 'Custom Code ',
'to' => $args['to'],
'subject' => $args['subject'],
'html' => $args['message'],
],
] );
// Возвращаем пустые аргументы, чтобы wp_mail() не пытался отправить повторно
return [
'to' => '',
'subject' => '',
'message' => '',
'headers' => '',
'attachments' => [],
];
} ); Чек-лист настройки SMTP
- ✅ Выбран почтовый сервис (Mailgun или SendGrid)
- ✅ Домен верифицирован в панели сервиса
- ✅ DNS-записи SPF, DKIM, DMARC добавлены и валидны
- ✅ Код подключения добавлен в
functions.phpчерезphpmailer_init - ✅ Пароли/API-ключи вынесены в
wp-config.php - ✅ Тестовое письмо доставлено во «Входящие»
- ✅ Оценка на mail-tester.com ≥ 9/10
- ✅ Плагины SMTP деактивированы
- ✅ Настроено логирование ошибок через
wp_mail_failed
Итог
Настройка SMTP через Mailgun или SendGrid без плагинов — это 20 строк кода, которые решают проблему доставки писем навсегда. Письма идут через авторизованный канал, подписаны DKIM и попадают во «Входящие». Отсутствие плагина означает меньше нагрузки на PHP, меньше запросов к базе данных и полную прозрачность того, что происходит с каждым письмом. В сочетании с Action Scheduler для фоновой отправки это создаёт надёжную почтовую инфраструктуру, которая работает одинаково хорошо на любом хостинге.