При программной отправке электронных писем из среды 1С:Предприятие разработчики часто сталкиваются с неприятной ситуацией: получатель видит текст письма, но вместо встроенных изображений отображаются пустые квадраты с красным крестиком. Эта проблема особенно актуальна при использовании почтовых клиентов сторонних разработчиков, таких как Thunderbird, Outlook или веб-интерфейса Gmail. В этой статье мы подробно разберем, почему это происходит, и изучим несколько надежных способов программной реализации вставки картинок.
Когда мы формируем письмо в формате HTML, для отображения картинки внутри текста используется тег img с атрибутом src. Если указать в этом атрибуте прямой путь к файлу на вашем диске, почтовый клиент получателя не сможет его прочитать, так как у него нет доступа к вашему локальному компьютеру. Чтобы картинка отобразилась, она должна быть либо размещена на внешнем веб-сервере (и иметь ссылку вида http://...), либо быть вложена в само письмо как ресурс.
Для связки текста HTML и вложенного файла используется механизм CID (Content-ID). В коде письма это выглядит как src="cid:уникальный_ид". Если почтовый клиент видит такой путь, он ищет среди вложений файл, у которого в заголовках прописан точно такой же идентификатор. Если идентификаторы не совпадают или не заданы вовсе, мы получаем тот самый «квадратик с крестом».
Рассмотрим самый простой и автоматизированный способ, который предоставляет платформа 1С. Суть метода заключается в том, что мы подготавливаем HTML-текст с локальными путями к картинкам, а система сама конвертирует их во вложения с нужными идентификаторами.
Разберем алгоритм по шагам:
ИнтернетПочтовоеСообщение.C:\Temp\image.png).ОбработатьТексты().Проанализируем пример кода:
Письмо = Новый ИнтернетПочтовоеСообщение;
Письмо.Тема = "Отчет с графиками";
Письмо.Отправитель = "sender@company.ru";
Письмо.Получатели.Добавить("client@gmail.com");
// Указываем локальный путь к файлу
ПутьККартинке = "C:\Temp\logo.png";
ТекстHTML = "<html><body>" +
"<p>Здравствуйте! Посмотрите наш логотип:</p>" +
"<img src=""file:///" + ПутьККартинке + """>" +
"</body></html>";
Письмо.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);
// Самый важный момент:
Письмо.ОбработатьТексты();
// Теперь можно отправлять
Почта = Новый ИнтернетПочта;
Почта.Подключиться(Профиль);
Почта.Послать(Письмо);
Важное примечание: При использовании этого метода 1С самостоятельно создает вложения, считывает данные с диска и заменяет в HTML-тексте локальный путь на конструкцию cid:идентификатор. Однако, как отмечают опытные разработчики, иногда 1С может присвоить временным файлам расширение .tmp, что блокируется некоторыми почтовыми фильтрами. Если этот способ не сработал, перейдем к более гибкому ручному управлению.
Если мы хотим полностью контролировать процесс и не зависеть от автоматических алгоритмов 1С, нам следует самостоятельно связать картинку в тексте с объектом вложения. Это наиболее надежный метод, который «пробивает» защиту большинства почтовых клиентов.
Посмотрим на пример реализации без сохранения временных файлов на диск, используя ДвоичныеДанные:
Письмо = Новый ИнтернетПочтовоеСообщение;
ИдентификаторКартинки = "img_logo_001"; // Произвольный уникальный ID
// 1. Формируем HTML со ссылкой через cid:
ТекстHTML = "<p>Логотип компании:</p>" +
"<img src=""cid:" + ИдентификаторКартинки + """>";
Письмо.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);
// 2. Добавляем саму картинку во вложения
// Предположим, картинка хранится в макете или базе как ДвоичныеДанные
КартинкаДД = Справочники.Файлы.НайтиПоНаименованию("Logo").ДанныеПуть.Получить();
Вложение = Письмо.Вложения.Добавить(КартинкаДД, "logo.png");
Вложение.Идентификатор = ИдентификаторКартинки; // Тот самый CID
Вложение.Наименование = "logo.png";
// Метод ОбработатьТексты в данном случае вызывать НЕ НУЖНО,
// так как мы все связали вручную.
В этом примере критически важно, чтобы значение в src="cid:..." полностью совпадало со свойством Идентификатор объекта ИнтернетПочтовоеВложение. Обратите внимание, что в атрибуте src приставка cid: обязательна, а в свойстве Вложение.Идентификатор ее быть не должно.
Если пользователь редактирует текст письма в специальном поле на форме (используя ФорматированныйДокумент), задача упрощается. Платформа уже хранит картинки внутри этого объекта в виде структуры.
Рассмотрим правильный алгоритм выгрузки:
ТекстHTML = "";
СтруктураКартинок = Новый Структура;
Объект.ФорматированныйДокумент.ПолучитьHTML(ТекстHTML, СтруктураКартинок);
Письмо = Новый ИнтернетПочтовоеСообщение;
Для Каждого Картинка Из СтруктураКартинок Цикл
// Ключ - это внутреннее имя картинки в HTML (например, "v8_img_1")
// Значение - это объект Картинка
ДД = Картинка.Значение.ПолучитьДвоичныеДанные();
ИмяФайла = Картинка.Ключ + ".png";
Вложение = Письмо.Вложения.Добавить(ДД, ИмяФайла);
Вложение.Идентификатор = Картинка.Ключ;
// Заменяем в HTML ссылки на правильный формат CID
ТекстHTML = СтрЗаменить(ТекстHTML, Картинка.Ключ, "cid:" + Картинка.Ключ);
КонецЦикла;
Письмо.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);
Проанализируем несколько тонкостей, которые помогут избежать блокировки картинок:
.jpg, .png). Почтовые клиенты часто отказываются отображать вложения без расширений или с расширением .tmp.data:image/png;base64,.... Мы не рекомендуем этот способ для массовых рассылок, так как многие корпоративные фильтры (включая Outlook) блокируют такой контент из соображений безопасности, а объем текста письма вырастает в разы.Таким образом, комбинируя правильное использование объекта ИнтернетПочтовоеСообщение и точную настройку Идентификатора вложения, мы можем добиться гарантированного отображения графической информации во всех современных почтовых системах. Если вам требуется быстро внедрить этот механизм для отправки писем при выполнении задач в 1С:Документооборот 3.0, можно воспользоваться готовым расширением для автоматической вставки картинок в тело писем.