Как исправить ошибку «Каталог не обнаружен» при отправке электронного письма с изображениями из форматированного документа 1С?

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

При разработке функционала отправки почтовых сообщений из 1С разработчики часто сталкиваются с ситуацией, когда текст письма формируется в объекте ФорматированныйДокумент. Если в такое поле вставить изображение через интерфейсную команду, то в момент программной отправки сообщения система может выдать непредвиденную ошибку «Каталог не обнаружен», а само письмо не отправляется.

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

Выясним причину возникновения ошибки

Проанализируем структуру текста, которую генерирует ФорматированныйДокумент. При вставке изображения в разметке формируется тег с атрибутом пути вида src="e1cib/formpict?formUUID=...&fdvalue=...".

Рассмотрим природу этого пути подробнее:

  1. Внутренний контекст платформы: адрес вида e1cib/formpict представляет собой внутреннюю навигационную ссылку платформы «1С:Предприятие». Она жестко привязана к идентификатору открытой формы (formUUID) и сессии конкретного пользователя. Вне пределов запущенного сеанса эта ссылка не существует и не имеет смысла для внешних почтовых клиентов.
  2. Сбой почтового движка: когда объект ПочтовоеСообщение пытается обработать HTML-текст для отправки, встроенный механизм почтового клиента платформы пытается проанализировать относительный адрес в теге src. Не распознавая внутренний протокол e1cib, платформа интерпретирует его как локальный путь файловой системы операционной системы на стороне сервера. В попытках найти указанную директорию система не находит соответствующего каталога на диске и генерирует исключение «Каталог не обнаружен».

Способ 1. Штатная выгрузка изображений и передача через Content-ID (CID)

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

Разберем по шагам реализацию этого механизма:

  1. Извлекаем HTML-текст и коллекцию изображений с помощью метода ПолучитьHTML объекта ФорматированныйДокумент. Метод заполняет строковую переменную разметкой, а также возвращает структуру, ключами которой являются имена картинок, а значениями — объекты типа Картинка.
  2. Обходим полученную структуру картинок в цикле, получаем двоичные данные каждого файла и добавляем их во вложения почтового сообщения.
  3. Устанавливаем уникальный идентификатор вложения через свойство Идентификатор.
  4. Заменяем внутренние имена изображений в HTML-коде на конструкцию cid:ИдентификаторВложения.
  5. Устанавливаем готовый текст в письмо с типом ТипТекстаПочтовогоСообщения.HTML.

Посмотрим на пример программного кода, реализующего этот алгоритм:


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

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

ПочтовоеСообщение = Новый ПочтовоеСообщение;
ПочтовоеСообщение.Тема = "Тема сообщения с изображениями";

Для Каждого ЭлементКартинка Из Картинки Цикл
    ДвоичныеДанные = ЭлементКартинка.Значение.ПолучитьДвоичныеДанные();
    
    // Добавляем картинку во вложения письма
    Вложение = ПочтовоеСообщение.Вложения.Добавить(ДвоичныеДанные, ЭлементКартинка.Ключ);
    
    // Присваиваем уникальный идентификатор контента
    ИдентификаторВложения = "img_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
    Вложение.Идентификатор = ИдентификаторВложения;
    
    // Заменяем внутреннее имя на ссылку Content-ID
    ТекстHTML = СтрЗаменить(ТекстHTML, ЭлементКартинка.Ключ, "cid:" + ИдентификаторВложения);
КонецЦикла;

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

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

Способ 2. Конвертация документа в PDF-файл

Если нет строгой необходимости отправлять форматированный текст непосредственно в теле письма, проанализируем альтернативное и простое решение, предложенное на форуме — отправку содержимого в виде вложенного PDF-документа.

Такой вариант имеет свои преимущества:

  1. Гарантия неизменности верстки: письмо будет выглядеть одинаково на любых устройствах, независимо от настроек почтовой программы клиента.
  2. Простота реализации: содержимое отправляется на печать через виртуальный PDF-принтер или сохраняется в файл формата PDF, после чего готовый документ добавляется в коллекцию ПочтовоеСообщение.Вложения обычным файлом.

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

Способ 3. Встраивание изображений в тело HTML через Base64

Рассмотрим подробнее еще один способ передачи — прямое внедрение данных формата Data URI в разметку HTML. Вместо создания отдельных вложений картинки можно закодировать в текстовую строку Base64.

Разберем последовательность действий:

  1. Получаем двоичные данные изображения с помощью метода ПолучитьДвоичныеДанные().
  2. Преобразуем двоичные данные в строку Base64 с помощью функции Base64Строка().
  3. Заменяем путь в атрибуте 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С:

  1. Объект ФорматированныйДокумент интерактивно заполняется пользователем на клиенте. В этот момент картинки временно существуют только в клиентском сеансе.
  2. Процедура отправки почты через ИнтернетПочта чаще всего выполняется на сервере. Если передать на сервер только текст HTML со ссылками e1cib, серверный контекст не будет иметь доступа к временным ресурсам клиента.
  3. Поэтому операцию извлечения картинок через ПолучитьHTML(ТекстHTML, Картинки) рекомендуется выполнять на клиенте, после чего помещать полученные двоичные данные во временное хранилище или передавать их на сервер в виде структуры двоичных данных для последующего включения во вложения.
← На главную