Как экранировать спецсимволы в строке при формировании HTML-письма в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматической отправке писем из 1С разработчики часто сталкиваются с задачей: необходимо внедрить произвольный текст, введенный пользователем (например, комментарий к заказу или примечание), в готовый HTML-шаблон электронного письма. Если в тексте встречаются спецсимволы разметки — угловые скобки, кавычки или амперсанд, почтовый клиент воспринимает их как элементы верстки. В результате часть текста исчезает, разметка письма ломается, а при наличии определенных символов может возникнуть уязвимость HTML-инъекции.

Проанализируем ситуацию и выясним, какими способами можно преобразовать произвольную строку в корректный и безопасный HTML-текст средствами платформы 1С:Предприятие.

Способ 1. Быстрое экранирование через функцию СтрЗаменить

Наиболее производительный и понятный способ для вставки фрагмента текста внутрь существующего HTML-шаблона — последовательная замена специальных символов на соответствующие HTML-сущности (named entities). Разберем по шагам, какие символы обязательно требуют экранирования:

  1. Символ амперсанда & заменяется на &
  2. Символ «меньше» < заменяется на &lt;
  3. Символ «больше» > заменяется на &gt;
  4. Двойная кавычка " заменяется на &quot;
  5. Одинарная кавычка ' заменяется на &#39;

Критически важный момент: замену амперсанда необходимо выполнять самым первым шагом! Если сначала заменить, например, < на &lt;, а затем выполнить замену амперсанда, то символ & внутри созданной мнемоники превратится в &amp;lt;, что приведет к искажению отображения в браузере или почтовом клиенте.

Посмотрим на пример функции безопасного экранирования:


Функция ЭкранироватьHTML(Знач ИсходныйТекст) Экспорт
    Результат = ИсходныйТекст;
    Результат = СтрЗаменить(Результат, "&", "&");
    Результат = СтрЗаменить(Результат, "<", "<");
    Результат = СтрЗаменить(Результат, ">", ">");
    Результат = СтрЗаменить(Результат, """", """);
    Результат = СтрЗаменить(Результат, "'", "'");
    Возврат Результат;
КонецФункции

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

Способ 2. Автоматическое экранирование через ЗаписьXML

Если мы не хотим вручную перечислять все возможные символы, можно воспользоваться встроенным платформенным механизмом потоковой сериализации. Объект ЗаписьXML при вызове метода ЗаписатьТекст выполняет экранирование автоматически по всем стандартам XML и HTML.

Рассмотрим, как реализовать такую функцию:


Функция ЭкранироватьСтрокуЧерезXML(Знач ИсходныйТекст) Экспорт
    Запись = Новый ЗаписьXML;
    Запись.УстановитьСтроку();
    Запись.ЗаписатьНачалоЭлемента("t");
    Запись.ЗаписатьТекст(ИсходныйТекст);
    Запись.ЗаписатьКонецЭлемента();
    
    СформированнаяСтрока = Запись.Закрыть();
    // Отрезаем временные теги <t> и </t>
    Результат = Сред(СформированнаяСтрока, 4, СтрДлина(СформированнаяСтрока) - 7);
    Возврат Результат;
КонецФункции

Такой подход защищает от любых пропущенных служебных знаков и выполняется значительно быстрее, чем построение тяжелых объектных моделей.

Способ 3. Преобразование через объекты ДокументHTML и ЗаписьDOM

В обсуждении на форуме был предложен способ с использованием объектной модели документа DOM. В платформе 1С объект ДокументHTML позволяет создать текстовый узел, который при выгрузке через ЗаписьDOM автоматически преобразует спецсимволы в безопасные сущности.

Посмотрим на пример из обсуждения:


Д = Новый ДокументHTML;
Узел = Д.СоздатьТекстовыйУзел("><&й");
Д.ЭлементДокумента.ДобавитьДочерний(Узел);

ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьHTML = Новый ЗаписьHTML;
ЗаписьHTML.УстановитьСтроку();
ЗаписьDOM.Записать(Д, ЗаписьHTML);
СтрокаHTML = ЗаписьHTML.Закрыть();

Разберем ограничения этого метода, о которых важно помнить:

  1. Избыточный каркас документа: при выгрузке ЗаписьDOM генерирует полный HTML-документ (включая служебные теги структуры). Встроить такой результат в середину существующего письма нельзя без дополнительной очистки от тегов.
  2. Повышенные накладные расходы: создание структуры DOM и ее парсинг требуют ощутимо больше ресурсов процессора, что может снизить скорость при массовой рассылке уведомлений.

Способ 4. Сохранение абзацев и форматирования через ФорматированныйДокумент

Если текст пользователя содержит не только спецсимволы, но и множественные переносы строк, списки или отступы, простого экранирования будет недостаточно: по правилам HTML все переводы строк (символы Символы.ПС) и подряд идущие пробелы схлопываются в один пробел.

Чтобы преобразовать текст целиком с сохранением абзацев в полноценный HTML-документ, используем объект ФорматированныйДокумент:


ТекстПользователя = "Первая строка с символами < и >" + Символы.ПС + "Вторая строка письма";

ФормДок = Новый ФорматированныйДокумент;
ФормДок.Добавить(ТекстПользователя);

СтрокаHTML = "";
ФормДок.ПолучитьHTML(СтрокаHTML, Новый Структура);
// В переменной СтрокаHTML сформирован готовый HTML-код с тегами переносов

Если же мы вставляем фрагмент в готовый шаблон вручную через строковую функцию, переносы строк можно дополнительно заменить тегом <br>:


БезопасныйТекст = ЭкранироватьHTML(ТекстПользователя);
БезопасныйТекст = СтрЗаменить(БезопасныйТекст, Символы.ПС, "<br>");

Также можно обернуть выводимый блок в контейнер со стилем style="white-space: pre-wrap;", что позволит сохранить все исходные пробелы и переводы строк без ручной расстановки тегов <br>.

← На главную