Отправка почты в Битрикс: почтовые события, 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 дней гарантии