Кратко: письма WordPress не доходят, потому что по умолчанию функция wp_mail() отправляет их через PHP-функцию mail() без логина и пароля — сервер-получатель считает такие письма подозрительными и прячет их в спам или отбрасывает вовсе. Лечение в три шага: SMTP-плагин (WP Mail SMTP или FluentSMTP), ящик на домене сайта и DNS-записи SPF/DKIM. Ниже — тест-сниппет для проверки почты за минуту, три способа настройки SMTP с готовым кодом, раздел про SPF/DKIM и таблица частых ошибок.
Почему письма WordPress не доходят: как работает wp_mail() по умолчанию
В ядре WordPress есть собственный почтовый механизм. Функция wp_mail() — обёртка над библиотекой PHPMailer, которая по умолчанию вызывает PHP-функцию mail() вашего хостинга. Схема выглядит просто: форма отправила данные → WordPress собрал письмо → PHP передал его локальному почтовому серверу → тот попытался доставить письмо на сервер получателя. Проблема в том, что на каждом шаге письмо остаётся «анонимным».
Вот почему письма, отправленные через mail(), почти всегда попадают в спам:
- Нет аутентификации. Письмо уходит без логина и пароля — как открытка без отправителя. Почтовые сервисы (Gmail, Яндекс, Mail.ru) доверяют письмам, отправленным с логином и паролем через SMTP, а «безликие» — нет.
- Неверный отправитель. Часто письмо подписано
wordpress@vashdomen.ruили вовсеnobody@имя-сервера-хостинга— домен отправителя не совпадает с доменом сайта, и спам-фильтр срабатывает мгновенно. - Отсутствуют SPF и DKIM. Получающий сервер проверяет DNS-записи домена: разрешено ли этому серверу вообще отправлять за него письма. Без записей доверия нет — есть запись в спаме.
- Хостинг может блокировать отправку. На многих shared-тарифах функция
mail()отключена или ограничена: письмо «успешно отправилось», но на деле его выбросил локальный фильтр.
Важно понимать: форма на сайте при этом честно говорит «Сообщение отправлено» — она вызвала wp_mail(), та вернула true. Правда ли письмо дошло, WordPress не знает. Поэтому диагностику начинаем не с формы, а с самой почты. Если вы пока не знакомы с тем, как в WordPress подключаются свои функции, сначала пробегитесь по материалу о том, как работают хуки WordPress: actions и filters, — без этого понимания половина кода ниже покажется магией.
И ещё одна частая ловушка новичков: письма теряются не из-за WordPress, а из-за окружения. Локальная сборка (OpenServer, XAMPP) вообще не умеет отправлять почту — там wp_mail() всегда молчит. А на хостинге письмо может уходить с задержкой через планировщик wp-cron, если плагин форм поставил отправку в очередь. Об этом — в разделе про логирование.
Быстрая диагностика: отправляет ли wp_mail() письма вообще
Прежде чем что-то настраивать, проверьте базовую отправку. Добавьте тестовый сниппет в functions.php дочерней темы:
add_shortcode( 'ds_mail_test', function () {
$to = get_option( 'admin_email' ); // почта админа из настроек сайта
$ok = wp_mail(
$to,
'Тест почты с сайта ' . get_bloginfo( 'name' ),
'Если видите это письмо — wp_mail() на сайте работает.'
);
return $ok
? 'Письмо отправлено на ' . $to . '. Проверьте «Входящие» и папку «Спам».'
: 'Отправка не удалась. Включите лог ошибок (раздел 10) и повторите.';
} ); Сниппет регистрирует шорткод [ds_mail_test]. Вставьте его на любую черновую страницу, откройте её — код отправит письмо на адрес администратора, указанный в «Настройки → Общие». Если вы собираете много таких разовых сниппетов, удобнее держать их в одном месте — у нас есть подборка полезных сниппетов для functions.php с похожими приёмами.
Дальше три сценария:
- Письмо во «Входящих» — базовая отправка работает, но это не гарантия: письмо к самому себе хостинг почти всегда доставит. Проблема всплывает на внешних получателях.
- Письмо в «Спаме» — классика: отправка идёт через
mail()без SMTP. Читаем разделы 3–6. - Письма нет нигде — либо
mail()отключена хостером, либо ошибка отправки. Переходите к разделу про логирование и обязательно заведите SMTP.
Для объективной оценки отправки используйте сервис mail-tester.com: он выдаёт уникальный адрес, на который нужно отправить письмо, и показывает оценку от 0 до 10 с расшифровкой — чего именно не хватает домену (SPF, DKIM, корректный заголовок). Цель — 10 из 10 после настройки SMTP.
Способ 1. Плагин WP Mail SMTP: настройка по шагам
Самый быстрый и безопасный путь для новичка — плагин WP Mail SMTP. Он перехватывает все вызовы wp_mail() и переправляет письма через SMTP-сервер с аутентификацией: письма идут так же, как если бы вы отправляли их из почтового клиента.
Пошаговый порядок:
- Создайте ящик на домене сайта — например,
no-reply@vashdomen.ru. Это делается в панели хостинга в разделе «Почта» (если почта не на хостинге, а у провайдера вроде Яндекс 360 — берите данные оттуда). Ящик именно на домене сайта, а не на gmail.com: письма от «чужого» домена от своего имени — прямая дорога в спам. - Установите плагин «WP Mail SMTP» из каталога плагинов. Про выбор и установку плагинов у нас есть отдельный гайд — топ-10 плагинов WordPress для начинающих.
- Заполните настройки. Мастер предложит провайдеров (Gmail, SendGrid, Brevo и другие) — если у вас обычная хостинг-почта, выбирайте Other SMTP. Данные берутся из панели хостинга:
- SMTP Host — например
smtp.vashdomen.ruилиmail.timeweb.ru(уточните у хостера); - Encryption — SSL для порта 465 или TLS для порта 587;
- SMTP Username — полный ящик
no-reply@vashdomen.ru; - SMTP Password — пароль ящика (или «пароль приложения», если у провайдера включена двухфакторка);
- From Email / From Name — тот же ящик и название сайта, включите «Force From Email».
- SMTP Host — например
- Отправьте тестовое письмо встроенной кнопкой «Email Test» и проверьте почтовый тестер из раздела 2.
Типичные грабли: порт 25 закрыт у хостера (используйте 465/587), пароль с пробелами скопирован вместе с лишним символом, а в поле From указан ящик с другого домена. Все эти случаи разбираем в таблице ошибок в разделе 11.
Альтернативные SMTP-плагины: что выбрать
WP Mail SMTP — не единственный вариант. Полезно знать альтернативы: некоторые дают лог писем бесплатно, другие проще в настройке. Сравнение:
| Плагин | Сложность | Лог писем | Особенности |
|---|---|---|---|
| WP Mail SMTP | Просто, мастер настройки | В Pro-версии | Де-факто стандарт, много инструкций, есть тест-письмо |
| FluentSMTP | Просто | Бесплатно, прямо в админке | Бесплатный лог и повторная отправка — удобно для форм |
| Post SMTP | Средняя | Бесплатно | Подробная диагностика соединения и конфигуратор |
| Easy WP SMTP | Просто | В новых версиях есть | Минимализм, только SMTP без внешних сервисов |
Практическая рекомендация: если нужен только «чтобы письма доходили» — берите WP Mail SMTP; если важно видеть каждое письмо и иметь возможность переслать потерянное — FluentSMTP. SMTP решает и проблему писем от контактных форм WordPress: уведомления с форм пойдут тем же надёжным каналом.
Способ 2. SMTP без плагина: сниппет phpmailer_init
Если не хотите лишний плагин (например, на сайте и так их два десятка), SMTP настраивается кодом через хук phpmailer_init — он срабатывает перед отправкой каждого письма и позволяет добраться до объекта PHPMailer:
// SMTP для wp_mail() без плагина
add_action( 'phpmailer_init', function ( $phpmailer ) {
$phpmailer->isSMTP();
$phpmailer->Host = 'smtp.vashdomen.ru'; // сервер исходящей почты
$phpmailer->Port = 465; // 465 = SSL, 587 = TLS
$phpmailer->SMTPAuth = true; // логин и пароль обязательны
$phpmailer->SMTPSecure = 'ssl'; // 'tls' для порта 587
$phpmailer->Username = 'no-reply@vashdomen.ru';
$phpmailer->Password = defined( 'DS_SMTP_PASS' ) ? DS_SMTP_PASS : '';
} );
// отправитель по умолчанию для всех писем сайта
add_filter( 'wp_mail_from', function () {
return 'no-reply@vashdomen.ru';
} );
add_filter( 'wp_mail_from_name', function () {
return get_bloginfo( 'name' );
} ); Обратите внимание на пароль: он подставляется из константы DS_SMTP_PASS. Определите её в wp-config.php, до строки «That’s all, stop editing!»:
define( 'DS_SMTP_PASS', 'parol-ot-yashchika' ); Почему не хранить пароль прямо в functions.php? Во-первых, это файл темы: пароль попадёт в резервные копии, репозиторий и любые экспорты кода. Во-вторых, редактор файлов в админке показывает содержимое всем, кто имеет доступ. Ключи в wp-config.php — минимальная гигиена из правил безопасности WordPress для новичков.
Код кладётся в functions.php дочерней темы или в mu-плагин в папке wp-content/mu-plugins. После вставки запустите тест из раздела 2 — письмо должно уйти уже через SMTP. Если PHPMailer выбрасывает ошибку соединения — сверьте пару «порт + шифрование»: комбинация «465 + tls» или «587 + ssl» — самая частая ошибка новичков.
SPF, DKIM и DMARC: чтобы письма не падали в спам
SMTP-плагин решает половину задачи: теперь письма аутентифицируются на отправке. Вторая половина — доказать миру, что ваш сервер имеет право отправлять письма от домена сайта. Это делают три DNS-записи, которые добавляются в панели управления доменом (там же, где вы настраивали домен для сайта):
- SPF — текстовая запись, перечисляющая серверы, которым разрешено отправлять почту от имени домена. Пример для сайта на хостинге Timeweb:
v=spf1 a mx include:_spf.timeweb.ru ~allТочный
includeу каждого хостера свой — он указан в инструкции к почте. - DKIM — цифровая подпись: сервер подписывает письмо ключом, а получатель сверяет подпись с публичным ключом в DNS. Ключ генерируется в панели хостинга при создании ящика — вам остаётся добавить TXT-запись вида
selector._domainkey.vashdomen.ru. - DMARC — политика: что делать получателю, если SPF/DKIM не сошлись. Для старта достаточно мягкой политики:
v=DMARC1; p=none; rua=mailto:admin@vashdomen.ruЧерез пару месяцев, убедившись, что легитимные письма проходят, ужесточайте до
p=quarantineилиp=reject.
После добавления записей подождите пару часов (DNS обновляется не мгновенно) и прогоните письмо через mail-tester.com. Если SPF или DKIM в отчёте красные — перепроверьте запись: лишний пробел или отсутствующая точка ломают синтаксис. Правильно настроенный конверт (SPF + DKIM + DMARC + согласованный From) — это 9 из 10 баллов тестера без единой строчки кода.
От кого идут письма: wp_mail_from и wp_mail_from_name
Даже с настроенным SMTP WordPress по умолчанию подставляет в поле «От» технический адрес wordpress@vashdomen.ru и имя «WordPress». Получатель видит подозрительное письмо от несуществующего ящика — доверия ноль, да и ответы на такое письмо уходят в никуда. Два фильтра это исправляют:
add_filter( 'wp_mail_from', function ( $from_email ) {
// единый адрес отправителя для всего сайта
return 'no-reply@vashdomen.ru';
} );
add_filter( 'wp_mail_from_name', function ( $from_name ) {
return 'Интернет-магазин Пчёлка'; // или get_bloginfo( 'name' )
} ); Три правила, которые нельзя нарушать:
- Домен адреса From должен совпадать с доменом сайта. Письмо «от поддержки@сайт.ру», отправленное через SMTP чужого домена, — гарантированный спам.
- Адрес From должен быть согласован с SPF — то есть домен из From входит в SPF-запись.
- Для ответов используйте Reply-To, а не From: ящик
no-reply@не читает входящие, а реальные вопросы клиентов должен получать живой человек:$headers = [ 'Reply-To: Отдел продаж <sales@vashdomen.ru>' ]; wp_mail( $to, $subject, $body, $headers );
HTML-письма, вложения и массовая отправка
wp_mail() умеет больше, чем «текст + тема». По умолчанию письма уходят в text/plain, но красивое письмо-уведомление с кнопками делается одним заголовком:
// HTML-письмо о новом заказе
$headers = [
'Content-Type: text/html; charset=UTF-8',
'Reply-To: sales@vashdomen.ru',
];
$body = '<h2 style="margin:0 0 12px">Заказ №128 принят</h2>'
. '<p>Клиент: ' . esc_html( $name ) . '</p>'
. '<p>Сумма: ' . esc_html( $total ) . ' ₽</p>'
. '<p><a href="https://vashdomen.ru/orders/128">Открыть заказ</a></p>';
wp_mail( 'manager@vashdomen.ru', 'Новый заказ №128', $body, $headers ); Пятый аргумент функции — вложения. Передавайте абсолютные пути к файлам на сервере, а не URL:
$upload = wp_get_upload_dir();
wp_mail(
'client@example.com',
'Счёт на оплату заказа №128',
'Здравствуйте! Счёт во вложении. Оплатить можно до 20.09.',
[],
[ $upload['basedir'] . '/invoices/invoice-128.pdf' ] // путь на сервере
); Массовая отправка — отдельная дисциплина. Если в цикле на 300 адресов вызвать wp_mail() подряд, скрипт упрётся в лимит времени PHP и часть писем уйдёт «в никуда». Правильный приём — поставить отправку в очередь через планировщик: каждое письмо отправляется отдельным запуском wp-cron, сайт не тормозит, а упавшая отправка повторяется. Для регулярных рассылок (новости, дайджесты) SMTP хостинга всё равно не годится — лимиты хостеров рассчитаны на уведомления, а не на рассылки; там используют сервисы вроде Unisender или Brevo, у которых wp_mail() настраивается тем же плагином из раздела 3.
Письмо с формы сайта: REST-endpoint и JavaScript
Соберём всё вместе: свой endpoint REST API, который принимает заявку с формы и отправляет её письмом через wp_mail(). Такую связку удобно делать, когда стандартные плагины форм избыточны. Про REST у нас есть подробный гайд — REST API WordPress простыми словами; здесь — рабочий минимум.
PHP: регистрируем маршрут /wp-json/ds/v1/contact:
add_action( 'rest_api_init', function () {
register_rest_route( 'ds/v1', '/contact', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => 'ds_contact_send',
'args' => [
'name' => [ 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ],
'email' => [ 'required' => true, 'sanitize_callback' => 'sanitize_email' ],
'message' => [ 'required' => true, 'sanitize_callback' => 'sanitize_textarea_field' ],
],
] );
} );
function ds_contact_send( WP_REST_Request $request ) {
// простая ловушка для ботов: скрытое поле должно остаться пустым
if ( $request['website'] ) {
return [ 'ok' => true ]; // боту говорим «спасибо» и молча игнорируем
}
$subject = 'Заявка с сайта: ' . $request['name'];
$body = "Имя: {$request['name']}\n"
. "E-mail: {$request['email']}\n\n"
. $request['message'];
$sent = wp_mail( get_option( 'admin_email' ), $subject, $body, [
'Reply-To: ' . $request['email'],
] );
if ( ! $sent ) {
return new WP_Error(
'mail_failed',
'Не удалось отправить заявку, позвоните нам.',
[ 'status' => 500 ]
);
}
return [ 'ok' => true ];
} JavaScript на фронте отправляет заявку без перезагрузки страницы:
var form = document.getElementById( 'ds-contact' );
form.addEventListener( 'submit', function ( e ) {
e.preventDefault();
var payload = {
name: form.elements.name.value,
email: form.elements.email.value,
message: form.elements.message.value,
website: form.elements.website.value, // honeypot
};
fetch( DS_SITE.rest + 'ds/v1/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
body: JSON.stringify( payload ),
} )
.then( function ( r ) { return r.json(); } )
.then( function ( res ) {
form.reset();
alert( res.ok
? 'Заявка отправлена! Ответим в течение часа.'
: 'Не получилось. Позвоните нам, пожалуйста.' );
} );
} ); Адрес REST и строку DS_SITE.rest передайте в скрипт через wp_localize_script():
wp_enqueue_script( 'ds-contact', get_stylesheet_directory_uri() . '/js/contact.js', [], '1.0', true );
wp_localize_script( 'ds-contact', 'DS_SITE', [
'rest' => esc_url_raw( rest_url() ),
] ); Здесь применены три предохранителя: аргументы маршрута чистятся через sanitize_callback (никаких сырых $_POST), скрытое поле-«honeypot» отсекает простых ботов, а Reply-To подставляет адрес клиента — можно отвечать прямо из почтового клиента. Для публичной формы добавьте капчу и ограничение частоты запросов — приёмы разобраны в статье про контактные формы WordPress.
Логирование ошибок: куда смотрят, когда письма «пропадают»
Самое неприятное в почте — молчание. Чтобы wp_mail() не терялась без следа, подпишитесь на событие wp_mail_failed — оно срабатывает при каждой неудачной отправке и отдаёт объект WP_Error с текстом ошибки от SMTP-сервера:
add_action( 'wp_mail_failed', function ( WP_Error $error ) {
error_log(
current_time( 'mysql' ) . ' mail failed: '
. $error->get_error_code() . ' — '
. $error->get_error_message()
);
} ); Чтобы записи попали в файл debug.log, включите в wp-config.php:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true ); // лог в wp-content/debug.log
define( 'WP_DEBUG_DISPLAY', false ); // ошибки не показывать посетителям После этого история с «пропавшими письмами» превращается в задачу на пять минут: в логе будет видно либо smtp_connect_failed (проблема сети/порта), либо 535 authentication failed (неверный логин/пароль), либо mail() on behalf of... (отправка всё ещё идёт мимо SMTP — проверьте настройки плагина).
Для просмотра лога не лезьте по FTP каждый раз: плагин Query Monitor покажет почтовые события прямо в админке, а FluentSMTP хранит каждое письмо с его статусом и текстом ошибки. И помните про очередь: если плагин форм ставит письма в отложенную отправку, ошибки всплывут не сразу, а при выполнении задачи крона — в его логе или в wp_mail_failed в момент запуска.
Частые ошибки SMTP и их решения
Сводная таблица ошибок, которые встречаются при настройке почты WordPress чаще всего:
| Симптом | Причина | Решение |
|---|---|---|
| 535 / Could not authenticate | Неверный логин или пароль, у провайдера включена 2FA | Проверьте логин (полный ящик) и создайте «пароль приложения» |
| Connection timed out (110) | Исходящий порт 25/465/587 закрыт на хостинге | Напишите в поддержку хостера открыть порт или смените порт |
| SSL/TLS handshake failed | Не совпадает шифрование и порт | 465 = SSL, 587 = STARTTLS (TLS); сверьте в настройках |
| Письма приходят в спам | Нет SPF/DKIM или From с чужого домена | Добавьте DNS-записи (раздел 6), единый From на домене сайта |
| Письма приходят с опозданием | Отправка в очереди через wp-cron, крон лагает | Переведите крон на серверный запуск по расписанию |
| From: wordpress@домен | Не заданы фильтры отправителя | wp_mail_from и wp_mail_from_name (раздел 7) |
| «Сообщение отправлено», писем нет | Форма вызывает wp_mail(), но mail() отключена хостером | Включите лог ошибок и настройте SMTP (разделы 3–5) |
Если разбираться с портами и DNS некогда — это штатная задача для поддержки: у нас есть разбор, что входит в поддержку сайта и сколько она стоит. Настройка почты там занимает один первый час.

Частые вопросы о почте WordPress и SMTP
Можно ли использовать Gmail или Яндекс-почту как SMTP для сайта?
Технически да: у Google и Яндекса есть SMTP-серверы и «пароли приложений» для сторонних программ. Но адрес отправителя будет с их домена, а не с домена сайта — часть получателей и спам-фильтров отнесётся к таким письмам плохо. Лучше завести ящик на своём домене у хостера или почтового провайдера и отправлять через него.
Какой порт и шифрование выбрать: 465 или 587?
Оба варианта рабочие: 465 работает по SSL сразу после подключения, 587 сначала открывает соединение открытым текстом и переключается на TLS командой STARTTLS. Главное — не смешивать: 465 требует в настройках «ssl», 587 — «tls». Если хостер поддерживает оба, начните с 465.
Где взять данные SMTP-сервера для настройки?
В панели хостинга в разделе «Почта» или в инструкции почтового провайдера: имя SMTP-сервера (обычно smtp.вашдомен.ru или сервер хостера), порт, тип шифрования и учётные данные — полный адрес ящика и пароль. Если данных нет в панели, их выдаст поддержка хостинга одним сообщением.
Обязательно ли ставить плагин, или достаточно кода в functions.php?
Достаточно кода: хук phpmailer_init с настройками SMTP полностью заменяет плагин (пример в разделе 5). Плагин удобнее новичку: есть мастер настройки, кнопка тест-письма и в некоторых версиях лог отправлений. Код выбирают, когда плагинов на сайте и так много или нужна жёсткая централизация настроек.
Почему письма всё равно попадают в спам даже с настроенным SMTP?
SMTP лишь аутентифицирует отправку. Если у домена нет SPF/DKIM, адрес From не согласован с этими записями или контент письма выглядит спамерски (кричащие заголовки, ссылки на сомнительные домены), письмо всё равно уедет в спам. Прогоните письмо через mail-tester.com — сервис покажет конкретную причину и подсказку.
Сколько писем можно отправлять с сайта, и что делать при больших объёмах?
Хостинг-почта рассчитана на уведомления: типичные лимиты — от сотен до пары тысяч писем в сутки, точные цифры у хостера. Превышение приводит к блокировке ящика. Для рассылок используйте специализированные сервисы (Brevo, Unisender): они подключаются тем же плагином WP Mail SMTP и выдерживают объёмы в десятки тысяч писем.
Вывод
Почта WordPress чинится по понятной цепочке: проверили базовую отправку тест-сниппетом → включили SMTP (плагином WP Mail SMTP или кодом через phpmailer_init) → задали единый отправитель фильтрами wp_mail_from/wp_mail_from_name → добавили SPF, DKIM и DMARC в DNS → включили лог wp_mail_failed, чтобы следующая проблема находилась за минуты, а не за дни. После каждого шага — тестовое письмо и mail-tester.com: цель 10 из 10 реально достижима за один вечер.
Если поднимаете сайт с нуля или форма — лишь часть задачи, посмотрите услуги разработки и настройки сайтов и живые кейсы в нашем портфолио; разборы SMTP, хуков и плагинов регулярно выходят в блоге о разработке WordPress. Нужна помощь с почтой на вашем сайте — напишите через форму контактов, настроим отправку и DNS так, чтобы письма доходили до клиентов, а не до папки «Спам».



