В WooCommerce лишние письма чаще всего появляются не из-за «ошибки почты», а из-за того, что один и тот же заказ проходит несколько переходов статуса: например, pending → processing → completed, а затем ещё раз обновляется плагином оплаты или складским модулем. В итоге клиент получает дубли, а менеджер — несколько одинаковых уведомлений.
Если задача именно в повторных письмах при смене статуса, отключать всю почту WooCommerce не нужно. Надёжнее точечно убрать отправку для конкретных переходов или для повторного срабатывания одного и того же уведомления.
Когда проблема действительно в WooCommerce, а не в почтовом сервере
Сначала стоит понять, где именно возникает дубль. Если письмо уходит дважды, это не всегда означает, что WooCommerce отправил его два раза. Иногда почтовый сервис повторяет доставку, а иногда письмо создаёт сторонний плагин через собственный хук.
Что проверить в первую очередь
- Откройте карточку заказа и посмотрите историю статусов: есть ли несколько переходов подряд в короткий промежуток времени.
- Проверьте, не установлен ли плагин для оплаты, CRM, склада или доставки, который тоже меняет статус заказа.
- Сравните заголовки письма в почтовом клиенте: если Message-ID разный, письмо, скорее всего, отправлено повторно на уровне сайта.
- Посмотрите, не включены ли одинаковые уведомления в нескольких плагинах для email-рассылок или транзакционных писем.
Если дубли появляются только при одном конкретном статусе, задача обычно решается фильтром или отключением нужного email-уведомления. Если письма дублируются на всех статусах, сначала ищите конфликт плагинов или повторный вызов save() у заказа.
Какие есть варианты решения
Для этой задачи есть три рабочих подхода: через настройки, через код и через отдельный плагин для управления письмами. Настройки подходят, если нужно просто отключить стандартное уведомление. Код нужен, когда письмо отправляется повторно из-за конкретного сценария. Плагин удобен, если магазином управляет не разработчик и нужно быстро менять правила без правки темы.
| Подход | Когда использовать | Плюсы | Минусы |
|---|---|---|---|
| Настройки WooCommerce | Нужно отключить стандартное письмо целиком | Быстро, без кода | Не решает дубли от сторонних плагинов |
| Код через фильтр | Нужно убрать письмо только для конкретного статуса или сценария | Точно, предсказуемо | Нужен доступ к теме или mu-plugin |
| Плагин управления email | Нужно дать доступ менеджеру без разработчика | Удобно для админки | Дополнительная зависимость и нагрузка |
Пошаговое решение через код
Если нужно отключить повторную отправку письма при переходе заказа в определённый статус, удобнее всего использовать фильтр woocommerce_email_enabled_{$email_id}. Он позволяет выключить конкретное письмо до отправки.
Ниже пример для случая, когда вы хотите отключить письмо о выполненном заказе, если оно уже было отправлено ранее, и не слать его повторно при повторном сохранении заказа.
<?php
add_filter( 'woocommerce_email_enabled_customer_completed_order', 'wpweb_disable_duplicate_completed_order_email', 10, 2 );
function wpweb_disable_duplicate_completed_order_email( $enabled, $order ) {
if ( ! $order instanceof WC_Order ) {
return $enabled;
}
// Кастомный флаг, чтобы не отправлять письмо повторно.
if ( $order->get_meta( '_wpweb_completed_email_sent' ) ) {
return false;
}
return $enabled;
}
add_action( 'woocommerce_order_status_completed', 'wpweb_mark_completed_email_sent', 20, 1 );
function wpweb_mark_completed_email_sent( $order_id ) {
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
if ( ! $order->get_meta( '_wpweb_completed_email_sent' ) ) {
$order->update_meta_data( '_wpweb_completed_email_sent', 'yes' );
$order->save();
}
}
Этот пример не отключает письмо навсегда для всех заказов. Он ставит метку в метаданных заказа после первого успешного перехода в статус completed. Если заказ снова сохранится тем же статусом, письмо уже не уйдёт повторно.
Если нужно отключить письмо только для одного статуса
Иногда задача проще: например, не отправлять клиенту письмо при переходе в processing, но оставить все остальные уведомления. Тогда можно отключить конкретный email-тип через фильтр.
<?php
add_filter( 'woocommerce_email_enabled_customer_processing_order', '__return_false' );
Этот вариант подходит только если вы уверены, что письмо не нужно вообще. Для защиты от дублей он слишком грубый: он выключит уведомление всегда, а не только при повторной отправке.
Диагностика: как понять, что письмо уходит повторно именно из-за статуса
Перед правкой кода полезно включить логирование. В WooCommerce можно временно добавить запись в лог при смене статуса заказа и посмотреть, сколько раз срабатывает один и тот же переход.
<?php
add_action( 'woocommerce_order_status_changed', 'wpweb_log_order_status_change', 10, 4 );
function wpweb_log_order_status_change( $order_id, $old_status, $new_status, $order ) {
if ( ! function_exists( 'wc_get_logger' ) ) {
return;
}
$logger = wc_get_logger();
$logger->info(
sprintf( 'Order #%d: %s -> %s', $order_id, $old_status, $new_status ),
array( 'source' => 'wpweb-order-status' )
);
}
После этого откройте WooCommerce → Статус → Логи и проверьте, не повторяется ли один и тот же переход несколько раз. Если статус меняется один раз, а письма приходят дважды, проблема уже не в этом хуке — тогда стоит искать повторную отправку через сторонний код или SMTP-плагин.
Проверка результата после внедрения
После добавления фильтра или метки не ограничивайтесь тестовым письмом в админке. Проверьте полный сценарий, который раньше создавал дубль.
- Создайте тестовый заказ с реальным переходом статуса.
- Переведите заказ в нужный статус вручную и через плагин оплаты, если именно он раньше создавал повтор.
- Проверьте, что письмо пришло один раз и только в нужный момент.
- Откройте карточку заказа и убедитесь, что мета-ключ
_wpweb_completed_email_sentпоявился один раз. - Посмотрите логи WooCommerce и почтового плагина, если он есть.
Если письмо не пришло вообще, значит фильтр сработал слишком рано или метка ставится до фактической отправки. В таком случае лучше перенести логику в более точный хук или убрать проверку на мета-ключ и тестировать отдельно.
Частые ошибки и как их исправить
Отключили не то письмо
В WooCommerce email-идентификаторы отличаются по назначению: customer_processing_order, customer_completed_order, new_order и другие. Если отключить не тот идентификатор, можно случайно убрать важное уведомление менеджеру или клиенту. Сначала проверьте, какое именно письмо дублируется, а уже потом вносите правку.
Добавили код в файл темы, который потом обновляется
Если вставить решение в functions.php активной темы, оно может исчезнуть после смены темы. Для стабильной работы лучше использовать небольшой mu-plugin или собственный плагин для сайта.
Не учли сторонний плагин оплаты
Некоторые платёжные модули повторно вызывают смену статуса после подтверждения оплаты. В этом случае отключение email-фильтра может помочь, но первопричина останется. Проверьте, не создаёт ли плагин повторный woocommerce_order_status_changed или повторное сохранение заказа.
Ставят глобальное отключение вместо точечной защиты
Фильтр __return_false удобен, но он выключает письмо всегда. Для магазина это часто слишком жёстко: менеджер перестаёт получать нужные уведомления, а клиент — важные письма о заказе.
Безопасность и производительность
Любая логика, которая пишет метаданные заказа, должна быть идемпотентной: повторный запуск не должен ломать состояние заказа. Не добавляйте запись в мета без проверки, если хук может сработать несколько раз подряд.
Если магазин большой, не делайте тяжёлые запросы в момент смены статуса. Проверка должна быть быстрой: чтение одного meta-поля и установка одного флага — нормальный сценарий. Не стоит вешать на этот хук запросы к внешним API или сложные выборки по базе.
Для магазинов, где администраторы часто меняют статусы вручную, полезно держать такое решение в отдельном мини-плагине. Так проще отключить его на время диагностики и не потерять код при обновлении темы.
Если вам нужно не только убрать дубли, но и навести порядок в уведомлениях, удобно смотреть в сторону специализированных инструментов управления сайтом. Например, в Clearfy Pro есть набор функций для чистки и отключения лишнего, но применять его стоит только там, где задача действительно решается настройками, а не бизнес-логикой заказа.
Что делать, если письма всё равно дублируются
Если после фильтра дубли остались, проверьте три вещи: не отправляет ли письмо SMTP-плагин повторно при ретрае, не дублирует ли уведомление CRM-интеграция, и не создаёт ли заказ повторный переход статуса из-за вебхука или callback от платёжной системы. В таких случаях проблема уже не в стандартной почте WooCommerce, а в цепочке интеграций вокруг заказа.
Самый практичный путь — временно отключить сторонние плагины по одному и повторить тестовый заказ. Так быстрее понять, где именно возникает повторная отправка, чем пытаться лечить всё одним универсальным хукoм.