Диагностика проблемы повторной отправки писем в WooCommerce
В WooCommerce стандартная логика отправки уведомлений срабатывает при каждом изменении статуса заказа. Часто это приводит к повторной отправке одного и того же письма, например, если статус возвращается к предыдущему или меняется несколько раз подряд. Это раздражает клиентов и увеличивает нагрузку на сервер. Чтобы решить проблему, необходимо понять, почему письма отправляются повторно и как контролировать этот процесс.
Как проверить, что письма отправляются несколько раз
- Просмотрите логи почты или плагина SMTP — найдите повторяющиеся уведомления на один и тот же заказ и статус.
- Отследите время изменения статуса заказа в админке — если несколько изменений подряд, это повод задуматься.
- Проверьте, не вызываются ли хуки отправки писем из сторонних плагинов или кастомных функций.
Пошаговое решение: условное исключение повторной отправки писем
Для контроля отправки писем нам понадобится перехватить процесс отправки уведомления и добавить условие, которое предотвратит повторную отправку при определённых условиях.
1. Используем хук woocommerce_email_enabled_{$email_id}
Этот фильтр позволяет включать или отключать отправку определённого письма. Например, для письма о смене статуса customer_processing_order или customer_completed_order.
add_filter('woocommerce_email_enabled_customer_completed_order', 'disable_repeated_email', 10, 2);
function disable_repeated_email($enabled, $order) {
// Проверяем, если условие для исключения выполнено
if (should_skip_email($order)) {
return false; // блокируем отправку
}
return $enabled;
}
function should_skip_email($order) {
// Например, исключаем повторную отправку, если мета-флаг уже установлен
return get_post_meta($order->get_id(), '_email_sent_completed', true) === 'yes';
}2. Устанавливаем мета-флаг при первой отправке
Чтобы пометить, что письмо уже отправлено, используем хук woocommerce_order_status_completed или аналогичный для нужного статуса.
add_action('woocommerce_order_status_completed', 'mark_email_as_sent');
function mark_email_as_sent($order_id) {
update_post_meta($order_id, '_email_sent_completed', 'yes');
}3. Сбрасываем мета-флаг при изменении статуса
Если заказ возвращается в статус, при котором письмо должно отправиться заново, сбрасываем мета-метку.
add_action('woocommerce_order_status_changed', 'reset_email_flag_on_status_change', 10, 4);
function reset_email_flag_on_status_change($order_id, $old_status, $new_status, $order) {
if ($new_status === 'processing') {
delete_post_meta($order_id, '_email_sent_completed');
}
}Проверка результата
После внедрения кода:
- Измените статус заказа на
completed— письмо должно отправиться и мета-флаг выставиться. - Попробуйте снова изменить на
completed— письмо не отправится повторно. - Смените статус на
processingи затем обратно наcompleted— письмо отправится снова. - Проверьте логи почты или используйте плагин для мониторинга SMTP.
Частые ошибки и как их исправить
- Неправильный ID письма в фильтре: убедитесь, что используете корректный идентификатор email (например,
customer_completed_order,new_orderи т.д.). - Метаданные не устанавливаются: проверьте, что
update_post_metaвызывается с правильным ID заказа и что хук срабатывает. - Повторная отправка из-за других плагинов: отключите сторонние плагины, которые могут влиять на отправку почты, и проверьте повторно.
- Кэширование данных: если используется кэширование объектов, убедитесь, что метаданные обновляются корректно.
Практические советы по производительности и безопасности
- Используйте транзиенты или мета-поля для хранения статуса отправки писем, чтобы не перегружать базу лишними запросами.
- Проверяйте права пользователя и данные заказа перед отправкой письма, чтобы исключить утечки информации.
- Минимизируйте количество хук-функций — объединяйте логику, чтобы не создавать избыточных вызовов.
- Для сложных сценариев используйте специализированные SMTP-плагины с логированием (например, WP Mail SMTP).
Сравнение подходов: плагин vs кастомный код
| Метод | Плюсы | Минусы |
|---|---|---|
| Плагин (например, Disable Emails) | Быстрая настройка, не требует кода, регулярные обновления | Может отключать письма глобально, мало гибкости, нагрузка на сайт |
| Кастомный код с хуками | Точная настройка по условиям, минимальная нагрузка, контроль логики | Требует знаний PHP, нужно тестировать при обновлениях WooCommerce |