В 1С-Битрикс письма отправляются не напрямую через mail(), а через слой почтовых событий: тип события, почтовый шаблон и отправка через CEvent::Send(). Такой подход даёт очередь, шаблонизацию, множество получателей и управление письмами из админки без правок кода.
Три сущности почтовой системы
Почтовая подсистема Битрикс состоит из трёх связанных объектов, и их важно не путать:
- Тип почтового события (
b_event_type) — логическое имя вродеNEW_ORDER, с описанием доступных полей; - Почтовый шаблон (
b_event_message) — конкретное письмо: тема, тело, отправитель, получатель. К одному типу можно привязать несколько шаблонов; - Почтовое событие (
b_event) — запись об отправке, которую разбирает агент рассылки.
Настройки → Настройки продукта → Почтовые события) без участия разработчика. Код лишь передаёт данные.Отправка письма через CEvent::Send()
Базовый вызов принимает код типа события, ID сайта и массив полей, которые подставятся в шаблон вместо #FIELD#.
$event = new CEvent;
$event->Send('NEW_ORDER', 's1', [
'ORDER_ID' => 1024,
'ORDER_USER' => 'Иван Иванов',
'EMAIL' => 'client@mail.ru',
'ORDER_TOTAL' => '15 900 ₽',
], 'Y', '', [], '', $bcc = '');
Четвёртый параметр ('Y') — использовать ли дублирование. Метод не отправляет письмо сразу: он создаёт запись в b_event, которую позже обработает агент CEvent::CheckEvents(). Поэтому в тестах письмо появляется с небольшой задержкой.
s1, а вы передали пустую строку или другой сайт — письмо просто не уйдёт, ошибок при этом не будет.Немедленная отправка: SendImmediate
Когда письмо нужно отправить синхронно (например, в API-ответе или при отладке), используйте CEvent::SendImmediate() — он формирует и отправляет письмо в текущем процессе, минуя очередь.
CEvent::SendImmediate('USER_INFO', SITE_ID, [
'USER_NAME' => 'Иван',
'EMAIL' => 'client@mail.ru',
]);
| Метод | Поведение | Когда применять |
|---|---|---|
Send() | кладёт в очередь, шлёт агент | обычная рассылка, массовые письма |
SendImmediate() | отправляет сразу | API, отладка, критичные уведомления |
Для нагруженных сценариев Send() предпочтительнее: он не блокирует пользовательский запрос на время SMTP-обмена.
Создание своего типа события и шаблона
Свой тип регистрируется через CEventType::Add(), шаблон — через CEventMessage::Add(). Обычно это делают в установщике модуля.
CEventType::Add([
'LID' => 'ru',
'EVENT_NAME' => 'MY_FEEDBACK',
'NAME' => 'Заявка с формы',
'DESCRIPTION' => '#NAME#, #EMAIL#, #MESSAGE#',
]);
CEventMessage::Add([
'EVENT_NAME' => 'MY_FEEDBACK',
'LID' => ['s1'],
'ACTIVE' => 'Y',
'EMAIL_FROM' => '#DEFAULT_EMAIL_FROM#',
'EMAIL_TO' => 'sales@company.ru',
'SUBJECT' => 'Новая заявка от #NAME#',
'BODY_TYPE' => 'html',
'MESSAGE' => '<p>#MESSAGE#</p>',
]);
Поле DESCRIPTION типа — это подсказка редактору о доступных плейсхолдерах. Константы вида #DEFAULT_EMAIL_FROM# подставляют системные настройки главного модуля.
Параметры и служебные поля
Помимо своих данных в шаблон можно передавать служебные поля, управляющие доставкой:
EMAIL_TO— переопределить получателя прямо из кода;EMAIL_FROM— отправитель;BCC— скрытая копия;CC— копия.
Значения из массива полей имеют приоритет над шаблоном, если в шаблоне стоит соответствующий плейсхолдер. Это удобно, когда получатель динамический — например, письмо клиенту по его адресу из заказа.
text, теги уйдут как есть. Для писем с версткой ставьте BODY_TYPE = 'html'.Вложения к письму
Файлы прикрепляются через седьмой параметр Send() — массив ID файлов из таблицы b_file.
$fileId = CFile::SaveFile([
'name' => 'invoice.pdf',
'type' => 'application/pdf',
'tmp_name' => $tmpPath,
], 'mail');
$event = new CEvent;
$event->Send('NEW_ORDER', 's1', $fields, 'N', '', [$fileId]);
Файл должен быть предварительно сохранён через CFile::SaveFile() — Битрикс работает с внутренним хранилищем, а не с произвольными путями на диске. Это важно учитывать при генерации счетов и накладных на лету.
Отладка и очередь рассылки
Если письма «не приходят», проверяйте по цепочке:
- шаблон активен (
ACTIVE = Y) и привязан к нужному сайту; - совпадает ID сайта в
Send()и в шаблоне; - запись появилась в очереди
b_eventсо статусомSUCCESS_EXEC = N; - работает агент
CEvent::CheckEvents()и настроена отправка (SMTP/sendmail); - в логе почты нет ошибок доставки.
Тип отправки (в очередь или сразу всей пачкой) настраивается в Настройки → Главный модуль → Способ отправки почты. На проде для стабильности часто выносят отправку в отдельную очередь и SMTP-релей.
Итог
Почтовые события — штатный способ слать письма в Битрикс: тип события описывает поля, шаблон отвечает за верстку и получателя, а CEvent::Send() ставит письмо в очередь (или SendImmediate() шлёт сразу). Свои типы и шаблоны регистрируются в установщике модуля, вложения идут через CFile, а отладка — по цепочке «шаблон → сайт → очередь → агент → SMTP».
Когда писем много и они завязаны на заказы, статусы и внешние системы, нужны надёжная очередь, ретраи и мониторинг доставки. Мы в B2Bsite настраиваем транзакционные рассылки и почтовую инфраструктуру так, чтобы уведомления доходили и не блокировали пользовательские запросы.
Частые вопросы
Чем CEvent::Send() отличается от SendImmediate()?
Send() создаёт запись в очереди b_event, а реальную отправку выполняет агент CEvent::CheckEvents(). SendImmediate() формирует и отправляет письмо сразу в текущем процессе, что удобно для API и отладки, но блокирует запрос на время SMTP-обмена.
Почему письмо не отправляется без ошибок?
Чаще всего не совпадает ID сайта в вызове Send() и в привязке шаблона, либо шаблон неактивен. Проверьте ACTIVE=Y, привязку к сайту и появление записи в очереди b_event.
Как передать получателя динамически?
Добавьте в массив полей ключ EMAIL_TO с нужным адресом и используйте плейсхолдер #EMAIL_TO# в поле получателя шаблона. Значение из кода переопределит статичный адрес шаблона.
Можно ли отправить HTML-письмо?
Да, задайте у шаблона BODY_TYPE = 'html'. При типе text теги в теле уйдут как обычный текст, а верстка не отобразится.
Как прикрепить файл к письму?
Сначала сохраните файл через CFile::SaveFile() и получите его ID, затем передайте массив ID в шестой параметр CEvent::Send(). Произвольные пути на диске система не принимает.
Где регистрировать свой тип почтового события?
В установщике модуля через CEventType::Add() для типа и CEventMessage::Add() для шаблона. Так письма появляются в админке и их текст можно править без вмешательства в код.
Что означают плейсхолдеры вида #DEFAULT_EMAIL_FROM#?
Это системные подстановки: адрес отправителя по умолчанию, имя сайта и другие значения из настроек главного модуля. Их удобно использовать, чтобы не хардкодить адреса в шаблонах.
Почему письма из очереди уходят с задержкой?
Send() лишь ставит письмо в очередь, а отправляет его агент по расписанию. Если нужна мгновенная доставка, используйте SendImmediate() или уменьшите интервал агента рассылки.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.