При отправке писем из системы 1С:Предприятие 8.3 разработчики часто сталкиваются с задачей встраивания изображений непосредственно в тело письма (HTML). Обычное прикрепление файлов во вложения не решает проблему, если картинка должна находиться в определенном месте текста. В этой статье мы подробно разберем, как правильно реализовать эту задачу, разберем типичные ошибки, связанные с методом ОбработатьТексты(), и рассмотрим современные автоматизированные способы платформы.
Для того чтобы почтовый клиент получателя (например, MS Outlook, Gmail или Яндекс.Почта) понял, что картинку нужно отобразить внутри текста, а не просто показать в списке вложений, используется специальный протокол связи. В HTML-коде письма ссылка на картинку должна указывать не на внешний сайт или локальный диск, а на уникальный идентификатор вложения.
Этот идентификатор называется CID (Content-ID). В HTML-коде тег картинки должен выглядеть следующим образом:
<img src="cid:УникальныйИдентификаторКартинки" />
При этом в само почтовое сообщение должно быть добавлено вложение с двоичными данными картинки, у которого свойству Идентификатор (в англоязычном синтаксисе — CID) присвоено точно такое же значение УникальныйИдентификаторКартинки.
Давайте по шагам разберем, как реализовать этот механизм программно в 1С различными способами.
Если в вашей конфигурации пользователь вводит текст с картинками в специальное поле на форме (имеющее тип ФорматированныйДокумент), то платформа предоставляет мощный встроенный инструмент, который берет на себя всю рутину по генерации уникальных ключей и связыванию картинок.
Давайте рассмотрим пример кода, который преобразует содержимое форматированного документа в готовое почтовое сообщение:
// Предположим, что СодержимоеДокумента - это реквизит формы с типом ФорматированныйДокумент
ТекстHTML = "";
СоответствиеКартинок = Новый Соответствие;
// Извлекаем HTML и сопоставленные картинки
СодержимоеДокумента.ПолучитьHTML(ТекстHTML, СоответствиеКартинок);
// Создаем почтовое сообщение
ПочтовоеСообщение = Новый ИнтернетПочтовоеСообщение;
ПочтовоеСообщение.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);
// Обходим полученное соответствие и добавляем картинки во вложения
Для Каждого КлючИЗначение Из СоответствиеКартинок Цикл
// КлючИЗначение.Ключ - это автоматически сгенерированный платформой CID (например, "image001")
// КлючИЗначение.Значение - это Картинка или ДвоичныеДанные изображения
Вложение = ПочтовоеСообщение.Вложения.Добавить(КлючИЗначение.Значение);
Вложение.Идентификатор = КлючИЗначение.Ключ; // Устанавливаем CID связи
КонецЦикла;
Этот способ является наиболее надежным и простым, поскольку метод ПолучитьHTML() гарантирует точное соответствие между именами в тегах src="cid:..." и ключами в возвращаемом соответствии картинок.
Иногда возникает ситуация, когда HTML-шаблон формируется вручную или загружается из внешнего источника, и нам необходимо самостоятельно прикрепить картинку. Рассмотрим, как правильно составить код в этом случае.
Выясним последовательность действий:
УникальныйИдентификатор).Идентификатор.Давайте проанализируем пример кода:
// Шаг 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", то при вызове метода платформа выполнит следующие действия автоматически:
picture.jpg с локального диска C:\Temp\.image001).C:\Temp\picture.jpg на cid:image001.В чем заключается ошибка разработчиков? Если вы уже вручную прописали в HTML-коде src="image001" или src="cid:image001" и при этом вызвали метод ОбработатьТексты(), система 1С попытается найти локальный файл с именем "image001" в текущем рабочем каталоге платформы. Разумеется, такого файла на диске нет, из-за чего выполнение программы прерывается ошибкой.
Важное правило: Если вы самостоятельно формируете связь через Вложение.Идентификатор = "ВашИдентификатор" и используете в коде конструкцию src="cid:ВашИдентификатор", вызывать метод ОбработатьТексты() для почтового сообщения категорически не нужно!
При копировании изображений из буфера обмена (например, скриншотов) непосредственно в поле форматированного документа в 1С, они часто сохраняются внутри HTML-кода как строка Base64. В коде это выглядит так:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSU..." />
Несмотря на то, что в самой 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;
КонецФункции
Применение этой функции гарантирует, что даже вставленные "на лету" скриншоты будут корректно доставлены получателю в виде стандартных вложений и правильно отобразятся в теле письма.