Как вставить картинку из форматированного текста в тело электронного письма в 1С

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

При отправке писем из системы 1С:Предприятие 8.3 разработчики часто сталкиваются с задачей встраивания изображений непосредственно в тело письма (HTML). Обычное прикрепление файлов во вложения не решает проблему, если картинка должна находиться в определенном месте текста. В этой статье мы подробно разберем, как правильно реализовать эту задачу, разберем типичные ошибки, связанные с методом ОбработатьТексты(), и рассмотрим современные автоматизированные способы платформы.

Понимание механизма CID (Content-ID)

Для того чтобы почтовый клиент получателя (например, MS Outlook, Gmail или Яндекс.Почта) понял, что картинку нужно отобразить внутри текста, а не просто показать в списке вложений, используется специальный протокол связи. В HTML-коде письма ссылка на картинку должна указывать не на внешний сайт или локальный диск, а на уникальный идентификатор вложения.

Этот идентификатор называется CID (Content-ID). В HTML-коде тег картинки должен выглядеть следующим образом:

<img src="cid:УникальныйИдентификаторКартинки" />

При этом в само почтовое сообщение должно быть добавлено вложение с двоичными данными картинки, у которого свойству Идентификатор (в англоязычном синтаксисе — CID) присвоено точно такое же значение УникальныйИдентификаторКартинки.

Давайте по шагам разберем, как реализовать этот механизм программно в 1С различными способами.

Способ 1. Использование встроенного объекта ФорматированныйДокумент (Рекомендуемый)

Если в вашей конфигурации пользователь вводит текст с картинками в специальное поле на форме (имеющее тип ФорматированныйДокумент), то платформа предоставляет мощный встроенный инструмент, который берет на себя всю рутину по генерации уникальных ключей и связыванию картинок.

Давайте рассмотрим пример кода, который преобразует содержимое форматированного документа в готовое почтовое сообщение:


// Предположим, что СодержимоеДокумента - это реквизит формы с типом ФорматированныйДокумент

ТекстHTML = "";
СоответствиеКартинок = Новый Соответствие;

// Извлекаем HTML и сопоставленные картинки
СодержимоеДокумента.ПолучитьHTML(ТекстHTML, СоответствиеКартинок);

// Создаем почтовое сообщение
ПочтовоеСообщение = Новый ИнтернетПочтовоеСообщение;
ПочтовоеСообщение.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);

// Обходим полученное соответствие и добавляем картинки во вложения
Для Каждого КлючИЗначение Из СоответствиеКартинок Цикл
    
    // КлючИЗначение.Ключ - это автоматически сгенерированный платформой CID (например, "image001")
    // КлючИЗначение.Значение - это Картинка или ДвоичныеДанные изображения
    
    Вложение = ПочтовоеСообщение.Вложения.Добавить(КлючИЗначение.Значение);
    Вложение.Идентификатор = КлючИЗначение.Ключ; // Устанавливаем CID связи
    
КонецЦикла;

Этот способ является наиболее надежным и простым, поскольку метод ПолучитьHTML() гарантирует точное соответствие между именами в тегах src="cid:..." и ключами в возвращаемом соответствии картинок.

Способ 2. Ручное формирование HTML и связывание картинок

Иногда возникает ситуация, когда HTML-шаблон формируется вручную или загружается из внешнего источника, и нам необходимо самостоятельно прикрепить картинку. Рассмотрим, как правильно составить код в этом случае.

Выясним последовательность действий:

  1. Создаем уникальный идентификатор для картинки (например, с помощью встроенного объекта УникальныйИдентификатор).
  2. Формируем HTML-текст, прописывая в теге изображения ссылку на созданный идентификатор.
  3. Добавляем двоичные данные картинки во вложения сообщения и устанавливаем свойство Идентификатор.

Давайте проанализируем пример кода:


// Шаг 1. Создаем уникальный идентификатор
УникальныйID = Новый УникальныйИдентификатор;
ИмяКартинкиСтрокой = Строка(УникальныйID);

// Шаг 2. Формируем HTML-текст письма
ТекстПисьмаHTML = "<html><body>";
ТекстПисьмаHTML = ТекстПисьмаHTML + "<p>Здравствуйте! Посмотрите на это изображение:</p>";
ТекстПисьмаHTML = ТекстПисьмаHTML + "<img src=""cid:" + ИмяКартинкиСтрокой + """ />";
ТекстПисьмаHTML = ТекстПисьмаHTML + "<p>С уважением, Ваша компания.</p>";
ТекстПисьмаHTML = ТекстПисьмаHTML + "</body></html>";

// Шаг 3. Создаем интернет-сообщение
ПочтовоеСообщение = Новый ИнтернетПочтовоеСообщение;
ПочтовоеСообщение.Тексты.Добавить(ТекстПисьмаHTML, ТипТекстаПочтовогоСообщения.HTML);

// Получаем двоичные данные картинки с диска или из макета
ПутьКФайлу = "D:\Images\logo.png";
КартинкаДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);

// Добавляем картинку во вложения и связываем по CID
НовоеВложение = ПочтовоеСообщение.Вложения.Добавить(КартинкаДвоичныеДанные);
НовоеВложение.Идентификатор = ИмяКартинкиСтрокой;

Подводные камни метода ОбработатьТексты()

Очень часто разработчики используют метод ПочтовоеСообщение.ОбработатьТексты(). Давайте разберем подробно, почему при его вызове может возникать популярная ошибка "Файл не найден".

Метод ОбработатьТексты() предназначен для автоматического преобразования локальных путей к файлам на компьютере в формат CID во вложениях. То есть, если в вашем HTML-коде написано src="C:\Temp\picture.jpg", то при вызове метода платформа выполнит следующие действия автоматически:

В чем заключается ошибка разработчиков? Если вы уже вручную прописали в HTML-коде src="image001" или src="cid:image001" и при этом вызвали метод ОбработатьТексты(), система 1С попытается найти локальный файл с именем "image001" в текущем рабочем каталоге платформы. Разумеется, такого файла на диске нет, из-за чего выполнение программы прерывается ошибкой.

Важное правило: Если вы самостоятельно формируете связь через Вложение.Идентификатор = "ВашИдентификатор" и используете в коде конструкцию src="cid:ВашИдентификатор", вызывать метод ОбработатьТексты() для почтового сообщения категорически не нужно!

Проблема картинок в формате Base64

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

<img src="data:image/png;base64,iVBORw0KGgoAAAANSU..." />

Несмотря на то, что в самой 1С такая картинка будет прекрасно отображаться, отправка письма в таком виде приведет к ряду проблем:

  1. Большинство современных почтовых систем (Gmail, Mail.ru, Outlook) в целях безопасности блокируют отображение картинок в формате Base64 или отправляют такие письма в спам из-за огромного объема текстовой части.
  2. При попытке отправки письма через встроенную почту 1С может выдать критическую ошибку об отсутствии файла по пути file:///data:image/....

Для корректной отправки таких писем перед отправкой рекомендуется программно находить все вхождения Base64 в тексте письма, преобразовывать их в двоичные данные и прикреплять к письму через стандартный механизм CID. Рассмотрим пример функции, которая решает эту задачу:


Функция ОбработатьКартинкиBase64(ТекстHTML, ПочтовоеСообщение) Экспорт
    
    // Регулярное выражение для поиска тегов картинок с base64 данными
    // Шаблон ищет совпадения вида src="data:image/png;base64,..."
    ШаблонПоиска = "src=""data:image/(?<Тип>\w+);base64,(?<Данные>[^""]+)""";
    
    РегВыражение = Новый COMОбъект("VBScript.RegExp");
    РегВыражение.IgnoreCase = Истина;
    РегВыражение.Global = Истина;
    РегВыражение.Pattern = ШаблонПоиска;
    
    РезультатыПоиска = РегВыражение.Execute(ТекстHTML);
    
    Для Каждого Совпадение Из РезультатыПоиска Цикл
        
        // Получаем закодированную строку и тип изображения
        СтрокаBase64 = Совпадение.SubMatches(1);
        РасширениеИзображения = Совпадение.SubMatches(0);
        
        // Преобразуем строку Base64 в двоичные данные 1С
        ДвоичныеДанныеКартинки = Base64Значение(СтрокаBase64);
        
        // Создаем уникальный CID
        НовыйCID = "img_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
        
        // Добавляем во вложения письма
        Вложение = ПочтовоеСообщение.Вложения.Добавить(ДвоичныеДанныеКартинки, "image." + РасширениеИзображения);
        Вложение.Идентификатор = НовыйCID;
        
        // Заменяем Base64 в HTML на ссылку CID
        ТекстHTML = СтрЗаменить(ТекстHTML, Совпадение.Value, "src=""cid:" + НовыйCID + """");
        
    КонецЦикла;
    
    Возврат ТекстHTML;
    
КонецФункции

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

← На главную