Как отправить вложения в WooCommerce email только для определенных статусов заказа

В WooCommerce вложения в письмах часто добавляют «в лоб»: подключают хук woocommerce_email_attachments и прикрепляют файл ко всем уведомлениям подряд. На практике это быстро приводит к лишним письмам с тяжелыми вложениями, жалобам от клиентов и проблемам с доставкой. Гораздо полезнее привязать файл только к нужным статусам заказа: например, к completed, processing или кастомному статусу, если вы отправляете договор, чек, инструкцию или акт только после определенного события.

Ниже разберем рабочую схему: как понять, где именно ломается логика, как ограничить вложения по статусу заказа, как проверить результат и какие ошибки встречаются чаще всего.

Когда вложение уходит не туда

Типичный сценарий выглядит так: вы добавили PDF в письмо, но он приходит и на new order админу, и на customer_on_hold_order, и на письмо о возврате. Иногда файл вообще прикрепляется к каждому письму, включая служебные уведомления. Это не только лишняя нагрузка, но и риск утечки документов, если вложение должно видеть только покупатель после оплаты.

Что проверить до правки кода

  • какой именно email-тип отправляет WooCommerce в вашем сценарии;
  • какой статус заказа должен запускать вложение;
  • один файл нужен всем письмам или только клиентским;
  • файл лежит в wp-content/uploads и доступен по пути на сервере;
  • нет ли второго плагина, который тоже добавляет вложения в письма.

Если вложение уже добавлялось через настройки плагина, сначала отключите этот механизм. Иначе вы будете отлаживать не свой код, а конфликт двух источников вложений.

Как ограничить вложение по статусу заказа

Самый надежный вариант — проверять статус заказа внутри фильтра woocommerce_email_attachments. Этот фильтр получает массив вложений, объект письма и объект заказа. Этого достаточно, чтобы прикрепить файл только к нужным уведомлениям.

Ниже пример для functions.php дочерней темы или небольшого mu-plugin. Он добавляет PDF только в письмо клиенту после завершения заказа.

<?php
add_filter( 'woocommerce_email_attachments', 'wpmail_attach_invoice_for_completed_order', 10, 4 );

function wpmail_attach_invoice_for_completed_order( $attachments, $email_id, $order, $email ) {
    if ( ! $order instanceof WC_Order ) {
        return $attachments;
    }

    // Только для письма клиенту о завершенном заказе.
    if ( 'customer_completed_order' !== $email_id ) {
        return $attachments;
    }

    if ( 'completed' !== $order->get_status() ) {
        return $attachments;
    }

    $file_path = WP_CONTENT_DIR . '/uploads/invoices/order-completed.pdf';

    if ( file_exists( $file_path ) ) {
        $attachments[] = $file_path;
    }

    return $attachments;
}

Если нужно привязать вложение к нескольким статусам, удобнее явно перечислить их в массиве. Так код остается читаемым и не превращается в набор вложенных if.

<?php
add_filter( 'woocommerce_email_attachments', 'wpmail_attach_file_for_selected_statuses', 10, 4 );

function wpmail_attach_file_for_selected_statuses( $attachments, $email_id, $order, $email ) {
    if ( ! $order instanceof WC_Order ) {
        return $attachments;
    }

    $allowed_email_ids = array( 'customer_processing_order', 'customer_completed_order' );
    $allowed_statuses  = array( 'processing', 'completed' );

    if ( ! in_array( $email_id, $allowed_email_ids, true ) ) {
        return $attachments;
    }

    if ( ! in_array( $order->get_status(), $allowed_statuses, true ) ) {
        return $attachments;
    }

    $file_path = WP_CONTENT_DIR . '/uploads/docs/order-guide.pdf';

    if ( is_readable( $file_path ) ) {
        $attachments[] = $file_path;
    }

    return $attachments;
}

Если нужен не один файл, а разные вложения для разных статусов

В реальных магазинах часто требуется не просто «прикрепить PDF», а выбрать файл по статусу. Например, после оплаты отправлять инструкцию, после завершения — гарантийный талон, а после ручной проверки — акт. В этом случае лучше собрать карту соответствий и не дублировать код.

<?php
add_filter( 'woocommerce_email_attachments', 'wpmail_attach_files_by_status_map', 10, 4 );

function wpmail_attach_files_by_status_map( $attachments, $email_id, $order, $email ) {
    if ( ! $order instanceof WC_Order ) {
        return $attachments;
    }

    $map = array(
        'customer_processing_order' => array(
            'processing' => WP_CONTENT_DIR . '/uploads/docs/processing-guide.pdf',
        ),
        'customer_completed_order' => array(
            'completed' => WP_CONTENT_DIR . '/uploads/docs/warranty.pdf',
        ),
    );

    if ( empty( $map[ $email_id ][ $order->get_status() ] ) ) {
        return $attachments;
    }

    $file_path = $map[ $email_id ][ $order->get_status() ];

    if ( is_readable( $file_path ) ) {
        $attachments[] = $file_path;
    }

    return $attachments;
}

Такой подход проще сопровождать: если меняется документ для статуса processing, вы правите одну строку, а не переписываете условия в нескольких местах.

Диагностика: как понять, почему вложение не прикрепилось

Если письмо уходит без файла, сначала проверьте не WooCommerce, а путь к документу. В большинстве случаев проблема банальна: неверный абсолютный путь, нет прав на чтение или файл лежит не там, где вы ожидаете.

Для отладки можно временно записывать данные в лог. Это безопаснее, чем выводить их в браузер или ломать отправку письма var_dump-ом.

<?php
add_filter( 'woocommerce_email_attachments', 'wpmail_debug_email_attachments', 10, 4 );

function wpmail_debug_email_attachments( $attachments, $email_id, $order, $email ) {
    if ( ! $order instanceof WC_Order ) {
        error_log( 'WPMail: order object missing for email ' . $email_id );
        return $attachments;
    }

    $file_path = WP_CONTENT_DIR . '/uploads/docs/warranty.pdf';

    error_log( 'WPMail: email=' . $email_id . ' status=' . $order->get_status() . ' file=' . $file_path );
    error_log( 'WPMail: exists=' . ( file_exists( $file_path ) ? 'yes' : 'no' ) . ' readable=' . ( is_readable( $file_path ) ? 'yes' : 'no' ) );

    return $attachments;
}

После тестовой отправки откройте wp-content/debug.log, если у вас включен WP_DEBUG_LOG. Если лог показывает exists=no, сначала исправляйте путь к файлу. Если readable=no — проверьте права доступа на сервере.

Проверка результата после внедрения

Не ограничивайтесь одним тестовым заказом. Лучше проверить минимум два сценария: нужный статус и статус, для которого вложение не должно уходить. Иначе можно случайно отправлять документы не тем получателям.

  1. Создайте тестовый заказ в WooCommerce.
  2. Переведите его в нужный статус, например processing или completed.
  3. Проверьте письмо в почтовом клиенте: есть ли вложение, правильный ли файл и не поврежден ли он.
  4. Повторите тест для статуса, который не должен добавлять файл.
  5. Если используете SMTP или почтовый API, проверьте, не режется ли письмо на стороне сервиса из-за размера вложения.

Полезно открыть исходник письма в почтовом клиенте и убедиться, что MIME-часть с вложением присутствует. Если файл есть в логике WordPress, но не доходит до ящика, проблема уже не в хуке, а в доставке или ограничениях почтового сервиса.

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

  • Вложение добавляется во все письма. Причина: нет проверки $email_id или статус заказа не фильтруется. Исправление: ограничьте и тип письма, и статус.
  • Файл не прикрепляется вообще. Причина: неверный абсолютный путь или файл недоступен для чтения. Исправление: используйте WP_CONTENT_DIR, file_exists() и is_readable().
  • Письмо уходит без ошибки, но вложение не видно. Причина: почтовый сервис режет вложения по размеру или клиент скрывает их в интерфейсе. Исправление: проверьте размер файла и отправку через другой ящик.
  • Вложение появляется дважды. Причина: файл добавляет и код, и плагин. Исправление: оставьте один источник логики.
  • Падает производительность на массовой отправке. Причина: файл собирается динамически или читается с медленного хранилища. Исправление: храните готовые документы локально и не генерируйте их на лету в фильтре отправки.

Безопасность и производительность: что не стоит делать

Не подставляйте путь к файлу из пользовательского ввода и не собирайте его из произвольных метаданных без проверки. Если заказчик может влиять на имя вложения, это уже зона риска: можно случайно открыть доступ к чужому файлу или попытаться прикрепить несуществующий путь.

Для чувствительных документов лучше хранить их в закрытой директории, а не в публичном каталоге без ограничений. Если файл должен быть доступен только после отправки письма, не делайте его угадываемым по URL.

Если у вас много заказов и тяжелые PDF, не генерируйте документ в момент отправки письма. Лучше подготовить файл заранее или вынести генерацию в отдельный процесс. Иначе отправка email станет узким местом в оформлении заказа.

Что выбрать: код, плагин или гибрид

ПодходКогда подходитМинус
Код через woocommerce_email_attachmentsНужна точная привязка к статусам и типам писемТребует поддержки в теме или mu-plugin
Плагин для PDF/документовНужно быстро без разработкиЧасто добавляет вложения шире, чем нужно
Гибрид: плагин для генерации, код для фильтрацииДокументы формирует плагин, а правила отправки задаете выНужно следить за совместимостью

Если у вас уже есть плагин для документов, не спешите от него отказываться. Часто достаточно отключить автоматическую отправку и оставить генерацию файла, а точку принятия решения перенести в код. Это дает контроль без полной переработки процесса.

Если вы хотите дальше чистить и упорядочивать email-логику магазина, удобно держать такие правки в отдельном mu-plugin, а не в functions.php. Тогда обновление темы не сломает отправку вложений и не затрет вашу логику.

Вам также может быть интересно:

WooCommerce: как настроить отправку email при неуспешной оплате заказа
19.08.2026
Как отключить emoji-скрипты в WordPress и убрать лишние запросы из фронтенда
29.08.2026
WP-Cron не запускается: как проверить и исправить отложенные задачи в WordPress
19.08.2026
Отложенная отправка email WooCommerce: как избежать блокировок при большом объеме писем
26.08.2026
Как выбрать SMTP-сервис для WordPress и проверить доставку писем
11.09.2026
×

AI-плагин от WPShop.ru

анализирует конкурентов

пишет статьи

готовит SEO

генерирует изображения

и еще кое-что...
WPGPT
Плагин, который наполняет ваш сайт WordPress
Узнать больше