wpmail.ru wordpress WP Mail

Как использовать отложенную отправку писем WooCommerce для снижения нагрузки и предотвращения блокировок

Почему важна отложенная отправка писем в WooCommerce

В интернет-магазинах на WooCommerce при большом количестве заказов массовая отправка писем (подтверждения, уведомления о статусе, счета) может привести к:

  • Перегрузке сервера хостинга из-за большого количества SMTP-сессий;
  • Блокировке почтового сервиса за подозрительную активность;
  • Замедлению работы сайта из-за синхронной отправки email;
  • Потере писем при ошибках в процессе отправки.

Отложенная отправка (email queue) помогает сгладить пики нагрузки, распределяя отправку писем во времени.

Диагностика проблем с отправкой писем WooCommerce

  • Проверьте логи почтового сервера и плагинов отправки (например, WP Mail Logging) — видны ли ошибки подключения или превышение лимитов?
  • Оцените нагрузку на PHP-процессы во время массовой отправки писем.
  • Подтвердите, что письма действительно уходят, но с задержкой или не уходят вовсе.

Пример логов ошибок при массовой отправке:

SMTP connect() failed. https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting

Пошаговое решение: реализация очереди отправки писем в WooCommerce

1. Отключаем синхронную отправку писем WooCommerce

По умолчанию WooCommerce отправляет письма сразу после события. Чтобы перейти к очереди, нужно перехватить отправку писем и поставить их в очередь.

2. Создаем таблицу для хранения очереди писем

function create_email_queue_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'email_queue';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
      id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
      to_email VARCHAR(255) NOT NULL,
      subject VARCHAR(255) NOT NULL,
      message LONGTEXT NOT NULL,
      headers LONGTEXT,
      attachments LONGTEXT,
      status VARCHAR(20) DEFAULT 'pending',
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY  (id)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
}
add_action('after_switch_theme', 'create_email_queue_table');

3. Перехватываем отправку писем WooCommerce и сохраняем в очередь

add_filter('woocommerce_email_actions', function($actions) {
    // Удаляем стандартные хуки отправки писем, чтобы контролировать самостоятельно
    return [];
});

add_action('woocommerce_order_status_completed', 'queue_order_completed_email', 10, 1);
function queue_order_completed_email($order_id) {
    $order = wc_get_order($order_id);
    if (!$order) return;

    $mailer = WC()->mailer();
    $email = $mailer->get_emails()['WC_Email_Customer_Completed_Order'];
    if (!$email) return;

    $to = $order->get_billing_email();
    $subject = $email->get_subject();
    $message = $email->get_content_html();
    $headers = $email->get_headers();
    $attachments = maybe_serialize($email->get_attachments());

    global $wpdb;
    $table = $wpdb->prefix . 'email_queue';
    $wpdb->insert($table, [
        'to_email' => $to,
        'subject' => $subject,
        'message' => $message,
        'headers' => $headers,
        'attachments' => $attachments,
        'status' => 'pending',
        'created_at' => current_time('mysql')
    ]);
}

4. Создаем WP-Cron задачу для отправки писем из очереди

add_action('send_email_queue', 'process_email_queue');
function process_email_queue() {
    global $wpdb;
    $table = $wpdb->prefix . 'email_queue';

    $emails = $wpdb->get_results("SELECT * FROM $table WHERE status = 'pending' ORDER BY created_at ASC LIMIT 10");
    if (!$emails) return;

    foreach ($emails as $email) {
        $sent = wp_mail($email->to_email, $email->subject, $email->message, maybe_unserialize($email->headers), maybe_unserialize($email->attachments));
        if ($sent) {
            $wpdb->update($table, ['status' => 'sent'], ['id' => $email->id]);
        } else {
            $wpdb->update($table, ['status' => 'failed'], ['id' => $email->id]);
        }
    }
}

if (!wp_next_scheduled('send_email_queue')) {
    wp_schedule_event(time(), 'five_minutes', 'send_email_queue');
}

add_filter('cron_schedules', function($schedules){
    $schedules['five_minutes'] = [
        'interval' => 300,
        'display' => __('Every 5 Minutes')
    ];
    return $schedules;
});

Как проверить, что отложенная отправка работает

  • Создайте тестовый заказ и переведите его в статус «Выполнен» — письмо не должно уйти мгновенно.
  • Проверьте таблицу wp_email_queue — в ней должен появиться новый записанный email с статусом pending.
  • Дождитесь запуска WP-Cron (или запустите вручную: wget -q -O - 'https://example.com/wp-cron.php?doing_wp_cron') и проверьте обновление статуса на sent или failed.
  • Проверьте почту получателя — письмо должно прийти с задержкой.

Частые ошибки и их исправление

  • Письма не отправляются — WP-Cron не работает. Проверьте, включен ли WP-Cron на сайте. Если нет, настройте системный cron-задание для вызова wp-cron.php.
  • Письма висят в статусе pending. Возможно, крон-задача не запущена. Вызовите ее вручную или проверьте логи ошибок.
  • Письма в статусе failed. Проверьте правильность параметров wp_mail() и корректность заголовков, вложений.
  • Скрипт не создает таблицу очереди. Убедитесь, что функция создания таблиц вызывается, например, при смене темы или вручную.

Практические советы по безопасности и производительности

  • Ограничивайте количество писем за один проход (например, 10), чтобы не нагружать сервер.
  • Используйте транзакции и блокировки для предотвращения одновременной обработки одних и тех же писем несколькими процессами.
  • Сохраняйте в базе только необходимые данные, не храните пароли и конфиденциальную информацию в письмах.
  • Для повышения надежности используйте внешние сервисы отправки SMTP или API (Postmark, SendGrid) совместно с очередью.
  • Включайте логирование отправленных писем и ошибок для оперативного мониторинга.

Сравнение вариантов реализации отложенной отправки

МетодПлюсыМинусыПример
Плагин WP Offload SES или аналогичныйПростота, интеграция с сервисом SMTP/API, отслеживаниеЗависимость от стороннего сервиса, стоимостьClearfy Pro (оптимизация и чистка)
Собственная очередь на базе базы данных и WP-CronПолный контроль, бесплатность, гибкостьНеобходимость поддержки и доработок, нагрузка на базуКод из статьи
Использование системного cron и внешних очередей (Redis, RabbitMQ)Максимальная производительность, масштабируемостьСложность настройки, требует серверного доступаТребует отдельной реализации
×

AI-плагин

WPGPT
Сам создает статьи для вашего сайта WordPress

SEO и мета-теги

Парсинг конкурентов

Изображения

Комментарии

Подробнее