Yandex Metrika
sanches.free 1 просмотр

События почтовой подсистемы Битрикс: OnBeforeMailSend, запись события и OnBeforeEventAdd

Где перехватывать логику

В «Главном модуле» исходящее письмо проходит несколько стадий: формируется запись о почтовом событии (тип, поля‑макросы, привязка к сайту и языку), подбирается шаблон, собираются заголовки и тело, затем пакет уходит транспорту. В зависимости от задачи удобнее цепляться либо к уже собранным параметрам отправки, либо к ORM‑событию добавления строки в таблице почтовых событий, либо к «классическому» событию до постановки в очередь.

OnBeforeMailSend: правка готового письма

Срабатывает, когда письмо уже сформировано из шаблона и ядро готовится к отправке. В обработчик передаётся \Bitrix\Main\Event; массив параметров берут так: $event->getParameter(0). Внутри — адресаты, тема, HTML‑тело, заголовки, идентификатор для трекинга, контекст доставки и прочие поля, которые дальше уйдут в почтовый транспорт.

Измените массив по месту и верните EventResult::SUCCESS с этим же массивом как данными результата — ядро подставит правленую версию. Для отладки на тестовом контуре достаточно логировать структуру через проектный логгер или AddMessage2Log, а не выводить print_r в ответ страницы.

use Bitrix\Main\EventManager;
use Bitrix\Main\Event;
use Bitrix\Main\EventResult;

EventManager::getInstance()->addEventHandler(
    'main',
    'OnBeforeMailSend',
    static function (Event $event): EventResult {
        /** @var array $mailParams */
        $mailParams = $event->getParameter(0);

        // Пример: дописать заголовок или изменить тему для выбранного типа.
        // if (($mailParams['HEADER']['X-EVENT_NAME'] ?? '') === 'SALE_ORDER_DELIVERY') { … }

        return new EventResult(EventResult::SUCCESS, $mailParams);
    }
);

OnBeforeAdd у почтового события (ORM)

Если нужно добавить или переопределить макрополя до шаблонизации, можно подписаться на событие сущности \Bitrix\Main\Mail\Internal\Event — точка входа в коде ядра названа OnBeforeAdd. В обработчике доступны поля будущей записи, в том числе массив C_FIELDS с подстановками для шаблона.

Важно: цепочка, которая использует CEvent::SendImmediate и обходит постановку записи в типичную очередь, может не заходить в этот обработчик. Для сценариев с немедленной отправкой закладывайте проверку на стенде или дублируйте логику на уровне OnBeforeEventAdd (см. ниже).

use Bitrix\Main\EventManager;
use Bitrix\Main\Mail\Internal\Event as MailEventEntity;
use Bitrix\Main\ORM\Event;
use Bitrix\Main\ORM\EventResult;

EventManager::getInstance()->addEventHandler(
    'main',
    MailEventEntity::class . '::OnBeforeAdd',
    static function (Event $event) {
        $fields = $event->getParameter('fields');

        if (($fields['EVENT_NAME'] ?? '') !== 'SALE_ORDER_DELIVERY') {
            return null;
        }

        $cFields = $fields['C_FIELDS'];
        $cFields['MY_NEW_FIELD'] = 'значение для макроса в шаблоне';

        $result = new EventResult();
        $result->modifyFields(['C_FIELDS' => $cFields]);

        return $result;
    }
);

Имена пространств имён (Entity vs ORM) в вашей сборке ядра могут отличаться; смысл — вернуть EventResult с изменёнными полями либо не трогать событие.

OnBeforeEventAdd: оба режима Send и SendImmediate

Отдельное событие OnBeforeEventAdd объявлено не в «документации D7» как отдельный модный класс, но вызывается и при обычной постановке, и при немедленной отправке. Сигнатура традиционна: по ссылке передаются имя типа события, $lid сайта, массив полей, идентификатор сообщения, файл и язык. Здесь удобно централизованно нормализовать поля для макросов или отфильтровать лишние отправки.

use Bitrix\Main\EventManager;

EventManager::getInstance()->addEventHandler(
    'main',
    'OnBeforeEventAdd',
    'MyMailHooks::onBeforeEventAdd'
);

class MyMailHooks
{
    public static function onBeforeEventAdd(
        &$eventName,
        &$lid,
        &$fields,
        &$messageId,
        &$files,
        &$languageId
    ): void {
        // Например: добавить поле или заменить плейсхолдер до выбора шаблона.
    }
}

Как выбрать точку

  • Нужно изменить уже сформированные заголовки или тело перед SMTP — чаще всего OnBeforeMailSend.
  • Нужно изменить сохраняемые макрополя в записи события и вы уверены, что сценарий проходит через ORM — Mail\Internal\Event::OnBeforeAdd с учётом ограничений SendImmediate.
  • Нужно покрыть и очередь, и немедленную отправку единообразно — начните с OnBeforeEventAdd и проверьте на своей версии ядра.

См. также

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии