При разработке функционала отправки почтовых сообщений из 1С разработчики часто сталкиваются с ситуацией, когда текст письма формируется в объекте ФорматированныйДокумент. Если в такое поле вставить изображение через интерфейсную команду, то в момент программной отправки сообщения система может выдать непредвиденную ошибку «Каталог не обнаружен», а само письмо не отправляется.
Разберем детально, почему возникает эта ошибка, как работает механизм хранения изображений внутри платформы и какими способами можно гарантированно отправить сформированное письмо адресату.
Проанализируем структуру текста, которую генерирует ФорматированныйДокумент. При вставке изображения в разметке формируется тег с атрибутом пути вида src="e1cib/formpict?formUUID=...&fdvalue=...".
Рассмотрим природу этого пути подробнее:
e1cib/formpict представляет собой внутреннюю навигационную ссылку платформы «1С:Предприятие». Она жестко привязана к идентификатору открытой формы (formUUID) и сессии конкретного пользователя. Вне пределов запущенного сеанса эта ссылка не существует и не имеет смысла для внешних почтовых клиентов.ПочтовоеСообщение пытается обработать HTML-текст для отправки, встроенный механизм почтового клиента платформы пытается проанализировать относительный адрес в теге src. Не распознавая внутренний протокол e1cib, платформа интерпретирует его как локальный путь файловой системы операционной системы на стороне сервера. В попытках найти указанную директорию система не находит соответствующего каталога на диске и генерирует исключение «Каталог не обнаружен».Рассмотрим штатный и наиболее правильный способ решения проблемы, который позволяет отправить полноценное HTML-письмо с встроенными изображениями. Для этого необходимо извлечь двоичные данные каждого изображения из документа, добавить их в коллекцию вложений письма и привязать к HTML-разметке с помощью идентификаторов cid.
Разберем по шагам реализацию этого механизма:
ПолучитьHTML объекта ФорматированныйДокумент. Метод заполняет строковую переменную разметкой, а также возвращает структуру, ключами которой являются имена картинок, а значениями — объекты типа Картинка.Идентификатор.cid:ИдентификаторВложения.ТипТекстаПочтовогоСообщения.HTML.Посмотрим на пример программного кода, реализующего этот алгоритм:
// Предположим, что ФорматированныйДок - это реквизит формы типа ФорматированныйДокумент
ТекстHTML = "";
Картинки = Новый Структура;
// Извлекаем HTML и структуру картинок
ФорматированныйДок.ПолучитьHTML(ТекстHTML, Картинки);
ПочтовоеСообщение = Новый ПочтовоеСообщение;
ПочтовоеСообщение.Тема = "Тема сообщения с изображениями";
Для Каждого ЭлементКартинка Из Картинки Цикл
ДвоичныеДанные = ЭлементКартинка.Значение.ПолучитьДвоичныеДанные();
// Добавляем картинку во вложения письма
Вложение = ПочтовоеСообщение.Вложения.Добавить(ДвоичныеДанные, ЭлементКартинка.Ключ);
// Присваиваем уникальный идентификатор контента
ИдентификаторВложения = "img_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
Вложение.Идентификатор = ИдентификаторВложения;
// Заменяем внутреннее имя на ссылку Content-ID
ТекстHTML = СтрЗаменить(ТекстHTML, ЭлементКартинка.Ключ, "cid:" + ИдентификаторВложения);
КонецЦикла;
// Добавляем результирующий текст в письмо
ПочтовоеСообщение.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);
При таком подходе почтовый клиент получателя корректно сопоставит вложенные файлы с тегами в теле письма, отобразив все элементы оформления без вызова системных ошибок.
Если нет строгой необходимости отправлять форматированный текст непосредственно в теле письма, проанализируем альтернативное и простое решение, предложенное на форуме — отправку содержимого в виде вложенного PDF-документа.
Такой вариант имеет свои преимущества:
ПочтовоеСообщение.Вложения обычным файлом.Для реализации этого метода текст письма в поле ПочтовоеСообщение.Тексты формируется простым информационным сообщением (например, с просьбой ознакомиться с прикрепленным файлом), а весь сформированный документ прикрепляется в качестве вложения.
Рассмотрим подробнее еще один способ передачи — прямое внедрение данных формата Data URI в разметку HTML. Вместо создания отдельных вложений картинки можно закодировать в текстовую строку Base64.
Разберем последовательность действий:
ПолучитьДвоичныеДанные().Base64Строка().src на строку вида data:image/png;base64,СтрокаBase64.Посмотрим на пример модификации разметки:
ТекстHTML = "";
Картинки = Новый Структура;
ФорматированныйДок.ПолучитьHTML(ТекстHTML, Картинки);
Для Каждого ЭлементКартинка Из Картинки Цикл
ДвоичныеДанные = ЭлементКартинка.Значение.ПолучитьДвоичныеДанные();
СтрокаBase64 = Base64Строка(ДвоичныеДанные);
// Формируем Data URI
DataURI = "data:image/png;base64," + СокрЛП(СтрокаBase64);
// Подставляем Data URI вместо внутреннего имени
ТекстHTML = СтрЗаменить(ТекстHTML, ЭлементКартинка.Ключ, DataURI);
КонецЦикла;
ПочтовоеСообщение.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);
Важный нюанс: учитывайте, что некоторые корпоративные почтовые клиенты (например, устаревшие версии Microsoft Outlook) могут блокировать показ изображений в формате Base64 в целях безопасности. В таких случаях наиболее стабильным решением остается Способ 1 с использованием CID.
При реализации отправки почты важно помнить о разделении контекстов выполнения кода в 1С:
ФорматированныйДокумент интерактивно заполняется пользователем на клиенте. В этот момент картинки временно существуют только в клиентском сеансе.ИнтернетПочта чаще всего выполняется на сервере. Если передать на сервер только текст HTML со ссылками e1cib, серверный контекст не будет иметь доступа к временным ресурсам клиента.ПолучитьHTML(ТекстHTML, Картинки) рекомендуется выполнять на клиенте, после чего помещать полученные двоичные данные во временное хранилище или передавать их на сервер в виде структуры двоичных данных для последующего включения во вложения.