Перейти к содержимому

Почтовые шаблоны - правка текста, макросы, второй сайт

Правим уже заведённое письмо: текст шаблона, макросы полей, отдельный вариант для второго сайта. Проверяем результат так, чтобы тестовые письма не ушли клиентам.

Решение

Какой шаблон сработает

Смотрим три привязки шаблона:

событие - имя типа, например SALE_NEW_ORDER
сайты - список ID: у второго сайта свой шаблон
активность - выключенный шаблон в отправке не участвует

Тип события описывает набор полей, а шаблон хранит тему, адреса и тело письма. У одного события бывает несколько активных шаблонов, и уходят они все сразу.

Макросы и их значения

Открываем описание типа события и читаем список полей:

#ORDER_ID# - номер заказа
#ORDER_USER# - имя покупателя
#ORDER_LIST# - состав заказа готовой разметкой

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

Кроме полей события шаблону доступны системные макросы:

#DEFAULT_EMAIL_FROM# - адрес отправителя из Главного модуля
#DEFAULT_SENDER# - имя отправителя
#SITE_NAME# - название сайта
#SERVER_NAME# - домен сайта

Значения системных макросов берутся из настроек Главного модуля. Значение, переданное отправляющим кодом под тем же именем, перебивает системное.

Текст письма и своё поле

Правим тело шаблона, подставляя макросы по именам:

<p>Здравствуйте, #ORDER_USER#!</p>
<p>Заказ #ORDER_ID# принят <?= date('d.m.Y') ?>.</p>
<p>Состав заказа: #ORDER_LIST#</p>

Переданные поля доступны в теле и макросом, и через массив параметров шаблона. Тело выполняется как PHP, поэтому короткая вставка с датой отправки работает.

Добавляем в письмо своё поле со стороны отправки:

CEvent::Send('SALE_NEW_ORDER', 's1', [
'ORDER_ID' => $orderId,
'ORDER_LIST' => $html, // ключа нет в вызове - в письме пустое место
]);

Макрос заполняет тот код, который отправляет письмо. Самописный обработчик заказа про штатные поля не знает, и в письме они окажутся пустыми.

Второй сайт и второй язык

Заводим отдельный шаблон того же события:

CEventMessage::Add([
'EVENT_NAME' => 'SALE_NEW_ORDER',
'LID' => ['s2'], // массив идентификаторов сайтов
'ACTIVE' => 'Y',
'EMAIL_FROM' => '#DEFAULT_EMAIL_FROM#',
'SUBJECT' => 'Order #ORDER_ID#',
'BODY_TYPE' => 'html',
'MESSAGE' => '<p>Your order is accepted.</p>',
]);

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

Тестовая отправка

Уводим все письма сайта на свой адрес:

/local/php_interface/init.php
define("ONLY_EMAIL", "dev@example.com"); // письма уйдут только сюда

Константа сильнее любых адресов шаблона, поэтому клиенты тестовых писем не увидят. После проверки её убирают, иначе боевые уведомления перестанут доходить.

Включаем служебные пометки в настройках Главного модуля:

all_bcc - копия каждого исходящего письма на служебный адрес
send_mid - ID события и шаблона прямо в тексте письма

Пометка отвечает на главный вопрос правки: какой именно шаблон сработал. Без неё два похожих письма от разных событий различить в ящике нечем.

Проверяем, что письмо вообще сформировалось:

SELECT ID, EVENT_NAME, SUCCESS_EXEC FROM b_event ORDER BY ID DESC LIMIT 5;
-- Y отправлены, P частично, F ни одного, 0 шаблон не найден, N не обработано

Значение 0 означает, что подходящего шаблона не нашлось совсем. Смотрят в этом случае имя события, привязку к сайту и флаг активности шаблона.

Вложения в письме

Прикладываем файл к письму по шаблону:

$fileId = \CFile::SaveFile($_FILES['file'], 'mailatt');
CEvent::Send('VENDOR_INVOICE', 's1', $fields, 'Y', '', [$fileId]);
// шестой параметр - массив ID файлов, а не путей к ним

Путь вместо идентификатора дублирует файл в хранилище, а имя вложения превращается в набор символов. Картинки в теле письма ставят абсолютной ссылкой: относительный адрес открывается уже вне сайта.

Типичные проблемы

Правили шаблон, а письмо приходит прежнее.

Правился шаблон другого сайта либо у события есть второй активный шаблон. Опция send_mid выводит идентификатор сработавшего шаблона прямо в письме.

На месте макроса состава заказа пусто.

Письмо отправляет свой код, который этот ключ в набор полей не передаёт. Платформа подстановки не проверяет и молча оставляет пустое место.

Письмо уходит с чужим адресом отправителя.

Поля «От кого» и «Кому» в шаблоне пусты, и подставляется адрес из настроек сайта. Когда пусто и там, оба поля берутся из настроек Главного модуля.

На втором сайте письмо приходит на чужом языке.

При отправке передан не тот идентификатор сайта, а язык и кодировка берутся из его настроек. Язык шаблона и язык сайта события должны совпадать.

Вложение пришло с именем из набора символов.

В параметрах передан путь к файлу вместо идентификатора зарегистрированного файла. Платформа при этом ещё и дублирует сам файл в хранилище.

Частые вопросы

Есть ли общий шаблон письма для сайта?

Общей обёрткой служит тема оформления писем: это шаблон сайта с типом mail, и лежит он рядом с обычными шаблонами. Штатную тему копируют из /bitrix/templates/ в /local/templates/ и правят копию, а стили подставляются inline в месте вызова showStyles: внешние таблицы стилей почтовые программы не грузят.

Где посмотреть список макросов конкретного письма?

В описании типа почтового события: это единственный перечень полей, который видит редактор шаблона. Список ведёт разработчик события, платформа его не проверяет, поэтому опечатка в имени макроса доживает до жалобы получателя.

Почему часть макросов в письме пустая?

Значение приходит от кода, который отправляет письмо, а системные макросы вроде #SITE_NAME# берутся из настроек Главного модуля. Если отправляющий код ключ не передал, в письме останется пустое место без всякой ошибки.

Можно ли в теле письма использовать PHP?

Да, тело шаблона выполняется, и короткая вставка с вызовом date подставит дату отправки. Переданные поля видны и макросом #KEY#, и через массив параметров шаблона.

Как проверить письмо и не задеть клиентов?

Определить константу ONLY_EMAIL в init.php: все письма сайта уйдут только на указанный адрес, независимо от адресов в шаблонах. После проверки константу убирают, иначе боевые уведомления перестанут доходить до покупателей.

Смежное

Первоисточник