Yandex Metrika
sanches.free 20 просмотров

Отправка почты в Битрикс: почтовые события, CEvent::Send и вложения

Модель: тип события и шаблон

В ядре исходящая почта обычно завязана на почтовые события: в админке задаётся тип (код вида CUSTOM_NOTICE) и один или несколько шаблонов с подстановками #FIELD#. PHP передаёт массив полей — ядро подставляет их в выбранный шаблон и ставит задачу на SMTP.

Перед экспериментами на бою имеет смысл завести отдельный тип события и тестовый ящик, чтобы не смешивать с боевой рассылкой регистрации и заказов.

CEvent::Send: очередь и флаг «копии»

Классический вызов — статический метод CEvent::Send: передаём код типа, идентификатор сайта (s1 и т. д.), массив полей и строку-признак дубля в адрес «общего исходящего» администратора. Значение "N" в последнем параметре как раз отключает эту копию, если политика проекта её не нужна.

$mailbox = 'subscriber@example.org';
$payload = [
    'USER_TO'   => $mailbox,
    'SUBJECT'   => 'Краткий заголовок',
    'MESSAGE'   => 'Текст письма в UTF-8',
];

$siteId = 's1';
CEvent::Send('CUSTOM_NOTICE', $siteId, $payload, 'N');

Если в шаблоне указан язык или привязка к сайту, а вы передаёте другой сайт или у шаблона нет версии под текущий язык контекста, письмо может «тишально» не уйти — имеет смысл проверить список шаблонов для типа и поле привязки к сайту/языку.

Когда письмо уходит сразу и как «дожать» очередь

Часть сценариев кладёт события в внутреннюю очередь; для ручного прогона на стенде или после сбоя транспорта можно вызвать обработчик очереди из API главного модуля: \Bitrix\Main\Mail\EventManager::executeEvents() — ориентируйтесь на документацию вашей версии ядра, это не замена настройке агента/cron для почты на продакшене.

Проверка из одноразового скрипта

Чтобы воспроизвести отправку вне запроса к странице, подключайте только мини-контекст ядра: корректный DOCUMENT_ROOT, при необходимости LANGUAGE_ID, типовые константы вроде NO_KEEP_STATISTIC и NOT_CHECK_PERMISSIONS, затем prolog_before.php. После этого вызывается тот же CEvent::Send уже с боевым типом события (например, стандартный NEW_USER_CONFIRM, если нужно просто проверить транспорт).

Тело письма с компонентом в шаблоне

В теле почтового шаблона допускается PHP — через подключение темы сообщения можно встроить компонент, который соберёт HTML (типичный пример в документации — задачи). Плейсхолдеры вроде {#TASK_ID#} подставляет механизм шаблонов до выполнения PHP; дальше компонент получает уже конкретные параметры. Держите такой шаблон простым: тяжёлая логика внутри письма усложняет отладку и нагружает отправку.

Вложение: файл из диска

Шестой аргумент CEvent::Send / смежных методов может принять массив идентификаторов файлов из медиабиблиотеки ядра. Файл сначала регистрируют через CFile::SaveFile (можно указать путь во временном каталоге), передают ID в отправку, а временную запись при необходимости удаляют после SendImmediate, чтобы не копить мусор в /upload/.

$tempPath = $_SERVER['DOCUMENT_ROOT'] . '/upload/tmp/price_export.txt';
// ... сформировать tempPath ...

$fileId = CFile::SaveFile(
    [
        'name'     => 'export.txt',
        'tmp_name' => $tempPath,
        'old_file' => '0',
        'del'      => 'N',
        'MODULE_ID'=> '',
    ],
    'mails'
);

$mail = new CEvent;
$mail->SendImmediate('PRICE_DELIVERY', 's1', $orderFields, 'N', '', [$fileId]);
CFile::Delete($fileId);

SendImmediate уместен там, где важно не откладывать отправку (и где вы контролируете, что вложение ещё существует на момент вызова). Для фоновых сценариев чаще оставляют обычную постановку в очередь и полагаются на штатный обработчик.

Итог

  • Описываете тип события и шаблоны в админке, из кода передаёте только поля и сайт.
  • Флаг "N" отключает копию администратору — уточняйте по политике проекта.
  • Следите за соответствием сайта/языка шаблона и контекста вызова.
  • Вложения — через CFile::SaveFile и массив ID; для «здесь и сейчас» смотрите SendImmediate.

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

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

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