Начать с одного корня и допустимых родителей

Самостоятельное письмо имеет корневой mjml, а содержимое находится в mj-body. Для обычного текстового блока используйте mj-section, внутри него mj-column, затем mj-text. Кнопка mj-button относится к той же колонке. Компилятор знает допустимые связи и атрибуты; здесь включена строгая валидация.

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

Официальные требования: MJML: документация компонентов письма · MJML: параметры strict, ignoreIncludes и fonts

Исправление родителя текстового блока
Исходные данные
<mj-body><mj-text>Заказ готов</mj-text></mj-body>
Результат
<mj-body><mj-section><mj-column><mj-text>Заказ готов</mj-text></mj-column></mj-section></mj-body>

Фрагмент поместите в единственный корневой mjml; это не весь документ.

Развернуть mj-include до загрузки

Шаблон с mj-include path="header.mjml" зависит от второго файла. В этом инструменте включения запрещены явно, даже если официальный компилятор умеет их игнорировать. Молчаливый пропуск шапки выглядел бы как успешное, но неполное письмо. URL в include также не загружается.

Соберите самостоятельный документ в своей рабочей среде: вставьте содержимое шапки и подвала на нужные места, сохранив правильные родители. Пользовательские .mjmlconfig, пакеты компонентов, пути, препроцессоры и skeleton из запроса не применяются. Если проект зависит от кастомных компонентов, используйте его локальную сборку.

Развернуть mj-include до загрузки
ЗависимостьПодготовка самостоятельного письма
mj-include с файлом или URLВставить проверенное содержимое локально
mj-font или CSS @importВыбрать системный стек шрифтов
Пользовательский компонент из .mjmlconfigКомпилировать проект в его собственной среде
HTTPS изображениеОставить URL и проверить загрузку у получателя

Выбрать системный шрифт и проверить переносы

Стандартные импорты веб-шрифтов выключены, mj-font отклоняется. Для примера задан Arial, sans-serif через mj-attributes и mj-all. Это не гарантирует наличие Arial на каждом устройстве: последнее семейство служит запасным вариантом. Разная метрика шрифта может изменить высоту кнопки и перенос длинной темы.

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

Использовать mj-raw только для известной пассивной разметки

mj-raw подходит для самостоятельной HTML-таблицы, которую уже проверили в почтовых клиентах. Этот блок не превращает произвольную веб-страницу в адаптивную секцию. Скрипт, обработчик событий, iframe, форма, опасный URL или внешняя таблица стилей запрещены и внутри raw.

mj-html-attributes также не поддерживается: этот компонент способен назначить произвольный атрибут уже созданному элементу. Для обычной ссылки используйте href самого mj-button; внедрять onclick через дополнительный компонент нельзя. Активное содержимое не разрешается спрятать в условном комментарии.

Условные комментарии и служебные таблицы готового результата нужны компилятору для разных клиентов. Не удаляйте их общей чисткой HTML после компиляции без сравнения. Обычный браузер и почтовая программа обрабатывают письмо по-разному; успешное открытие в браузере не заменяет тестовую отправку.

Проверить минимальный пример прежде большого письма

Вход ограничен 250000 байт UTF-8, 2000 элементами и 40 уровнями вложенности. Результат — до 20 МБ, а произведение числа элементов и суммы символов CSS и атрибутов MJML — до 8000000. При кодировке Windows-1251 сначала преобразуйте исходник в UTF-8: неверные байты не заменяются молча испорченными буквами. Минимальный пример помогает отличить ошибку структуры от ошибки кодировки.

Нажмите «Пример» и получите уведомление с текстом заказа и ссылкой example.com/order/42. Затем добавляйте реальные секции по одной, проверяя результат. Не используйте боевой список адресов для этого шага: инструмент не нуждается в получателях и ничего не отправляет.

  1. Скомпилируйте встроенный самостоятельный пример.
  2. Перенесите проверенные секции своего шаблона, без includes и imports.
  3. Исправьте ошибки strict; скачайте HTML только после успешного завершения.

Разделить компиляцию и подготовку MIME-рассылки

В готовом HTML найдите текст заказа и точный href кнопки; убедитесь, что компоненты MJML исчезли, а адаптивные правила остались. URL изображений остаются URL, сервер их не загружает. Для cid ваш сервис рассылки должен добавить соответствующие MIME-вложения; компилятор не создаёт их из одного шаблона.

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

Вопросы и ответы

Используется ли настоящий компилятор MJML?

Да. Официальный MJML 5.4.1 разворачивает компоненты в HTML и проверяет их в режиме strict. Ошибка структуры останавливает выдачу файла; результат не строится простой заменой тегов.

Почему не работает mj-include?

Включения явно запрещены до компиляции. Соберите один самостоятельный документ локально и вставьте содержимое зависимых шаблонов. Сервер не читает пути к файлам и не загружает шаблоны по URL.

Почему не загружаются Google Fonts и mj-font?

Стандартные веб-шрифты отключены параметром fonts: {}, а mj-font отклоняется. Укажите стек системных шрифтов, например Arial, sans-serif; наличие конкретного шрифта зависит от устройства получателя.

Что делать с ошибкой расположения mj-text?

Поместите mj-text внутрь mj-column, а колонку — внутрь mj-section в mj-body. Strict проверяет допустимые родительские компоненты и их атрибуты. Не убирайте проверку ради выдачи ошибочного письма.

Можно ли использовать mj-raw?

Можно для пассивной HTML-разметки, например самостоятельной таблицы. Активные теги, обработчики событий, внешние CSS и опасные URL запрещены также внутри mj-raw. Такой блок не получает автоматическую адаптивную раскладку компонентов MJML.

Можно ли сразу отправить результат подписчикам?

HTML можно перенести в ваш сервис рассылки, но сначала нужна тестовая отправка. Инструмент не создаёт MIME-письмо, не прикрепляет cid-изображения, не проверяет доставляемость и не подтверждает одинаковый вид во всех почтовых клиентах.