Настройка SMTP для WordPress: Mailgun и SendGrid Без Плагинов

Письма о новых комментариях, сбросе пароля или заказах 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:

  1. Зарегистрируйтесь на mailgun.com
  2. Создайте новый домен (например, mg.custom-code.ru)
  3. Добавьте DNS-записи (TXT для SPF/DKIM, MX для входящих) — Mailgun покажет точные значения
  4. Перейдите в Sending → Domains → выберите домен → SMTP credentials
  5. Скопируйте: SMTP hostname (smtp.mailgun.org), порт (587), логин (postmaster@mg.custom-code.ru) и пароль

Для SendGrid:

  1. Зарегистрируйтесь на sendgrid.com
  2. Перейдите в Settings → Sender Authentication → Verify Your Single Sender Identity
  3. Подтвердите email отправителя
  4. Перейдите в Settings → API Keys → Create API Key → выберите Full Access или Restricted Access (Mail Send)
  5. Скопируйте 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=100

p=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-ключ, а не пароль от аккаунта

Письма уходят, но попадают в спам

Проверьте три вещи:

  1. DNS-записи SPF/DKIM/DMARC настроены и валидны (проверьте через mail-tester.com)
  2. Домен отправителя (From) совпадает с верифицированным доменом в Mailgun/SendGrid
  3. Репутация домена не испорчена предыдущими рассылками (проверьте через 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 для фоновой отправки это создаёт надёжную почтовую инфраструктуру, которая работает одинаково хорошо на любом хостинге.