Как правильно отправить электронное письмо с вложениями из 1С:Предприятие 8

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

Автоматическая отправка писем с вложенными файлами (актами сверки, печатными формами документов, отчетами) — одна из наиболее частых задач при интеграции 1С с внешними системами и автоматизации бизнес-процессов. Однако у начинающих разработчиков нередко возникают сложности при попытке прикрепить файлы, которые хранятся внутри базы данных в реквизитах с типом ХранилищеЗначения.

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

Методика работы с Хранилищем Значения

Основная ошибка при работе со встроенными файлами в 1С заключается в попытке передать сам объект ХранилищеЗначения непосредственно во вложение почтового сообщения. Объект ХранилищеЗначения — это лишь системная «обертка», сжатая платформа для хранения информации в базе данных. Чтобы получить реальные данные файла, эту обертку необходимо предварительно раскрыть.

Выясним причину проблемы на примере кода. Для извлечения информации мы должны использовать метод Получить() объекта ХранилищеЗначения. В результате выполнения этого метода мы получаем объект типа ДвоичныеДанные. Рассмотрим правильный способ извлечения данных из базы с помощью запроса на сервере:


&НаСервере
Функция ПолучитьДанныеФайлаИзБазы(СсылкаНаФайл)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Файлы.ИмяКП1 КАК ИмяФайла,
        |	Файлы.Файл КАК ХранилищеФайла
        |ИЗ
        |	Справочник.Файлы КАК Файлы
        |ГДЕ
        |	Файлы.Ссылка = &Ссылка";
        
    Запрос.УстановитьПараметр("Ссылка", СсылкаНаФайл);
    РезультатЗапроса = Запрос.Выполнить();
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    
    СтруктураРезультата = Новый Структура("ИмяФайла, ДвоичныеДанные", "", Неопределено);
    
    Если ВыборкаДетальныеЗаписи.Следующий() Тогда
        СтруктураРезультата.ИмяФайла = ВыборкаДетальныеЗаписи.ИмяФайла;
        
        // Получаем объект ХранилищеЗначения из выборки
        ТекущееХранилище = ВыборкаДетальныеЗаписи.ХранилищеФайла;
        
        Если ТипЗнч(ТекущееХранилище) = Тип("ХранилищеЗначения") Тогда
            // Извлекаем непосредственно ДвоичныеДанные файла
            СтруктураРезультата.ДвоичныеДанные = ТекущееХранилище.Получить();
        КонецЕсли;
    КонецЕсли;
    
    Возврат СтруктураРезультата;
    
КонецФункции

Обратите внимание, что оборачивать извлеченные двоичные данные в объект Картинка (как иногда ошибочно делают разработчики при работе с изображениями) не требуется. Объект ИнтернетПочтовоеСообщение умеет напрямую работать с чистыми двоичными данными любых типов файлов: текстовых документов, PDF, Excel или архивов.

Добавление вложений в ИнтернетПочтовоеСообщение

Рассмотрим подробнее синтаксис метода добавления вложений. Метод СообщениеПочты.Вложения.Добавить() крайне гибок и поддерживает два основных сценария работы:

  1. Прямая передача двоичных данных из оперативной памяти: этот способ идеален для небольших файлов. Нам не требуется выполнять лишние дисковые операции записи и чтения. Мы передаем объект ДвоичныеДанные вторым параметром, а первым — желаемое имя файла для отображения у получателя.
  2. Передача через временный файл на диске сервера: этот способ рекомендуется использовать при отправке очень тяжелых вложений (более 10–15 Мб). Это позволяет избежать чрезмерной нагрузки на оперативную память рабочего процесса rphost.

Проанализируем пример кода для первого способа (наиболее быстрого и современного):


// Прямое добавление двоичных данных во вложение
СообщениеПочты = Новый ИнтернетПочтовоеСообщение;
СообщениеПочты.Тема = "Отправка вложенного файла";
СообщениеПочты.Получатели.Добавить("recipient@example.com");

// Добавляем вложение напрямую из оперативной памяти
СообщениеПочты.Вложения.Добавить(ДанныеФайла.ДвоичныеДанные, ДанныеФайла.ИмяФайла);

Если же файлы имеют внушительный объем, разберем по шагам безопасный алгоритм записи во временный каталог сервера с последующей отправкой и обязательной очисткой дискового пространства:


// Использование временного файла для тяжелых вложений
ИмяВременногоКаталога = КаталогВременныхФайлов();
ПолныйПутьКФайлу = ИмяВременногоКаталога + ДанныеФайла.ИмяФайла;

// Записываем двоичные данные на диск сервера
ДанныеФайла.ДвоичныеДанные.Записать(ПолныйПутьКФайлу);

СообщениеПочты = Новый ИнтернетПочтовоеСообщение;
СообщениеПочты.Вложения.Добавить(ПолныйПутьКФайлу, ДанныеФайла.ИмяФайла);

// Выполняем отправку почты...
// [Код отправки]

// Обязательно удаляем временный файл после закрытия почтового сеанса
Попытка
    УдалитьФайлы(ПолныйПутьКФайлу);
Исключение
    ЗаписьЖурналаРегистрации("ОтправкаПочты.ОшибкаУдаленияФайла",
        УровеньЖурналаРегистрации.Предупреждение, , , 
        ОписаниеОшибки());
КонецПопытки;

Настройка безопасного подключения SMTP (Яндекс, Mail.ru, Gmail)

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

Проанализируем ключевые требования современных почтовых систем к безопасности внешних приложений:

Посмотрим на пример правильного заполнения объекта ИнтернетПочтовыйПрофиль для работы с сервисом Яндекс.Почта:


Профиль = Новый ИнтернетПочтовыйПрофиль;
Профиль.АдресСервераSMTP = "smtp.yandex.ru";
Профиль.ПортSMTP = 465;
Профиль.ИспользоватьSSLSMTP = Истина; // Обязательное использование защищенного соединения

Профиль.АутентификацияSMTP = СпособSMTPАутентификации.Login;
Профиль.ПользовательSMTP = "my_mailbox@yandex.ru";
// Вместо реального пароля указываем сгенерированный пароль приложения
Профиль.ПарольSMTP = "abcd-efgh-ijkl-mnop"; 

Профиль.ВремяОжидания = 30; // Увеличиваем таймаут для работы с вложениями

Безопасная отправка почты с обработкой исключений

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

Объединим все наши наработки в единую надежную серверную процедуру:


&НаСервере
Процедура ОтправитьПисьмоСВложениемНаСервере(СсылкаНаФайл, АдресПолучателя, ТемаПисьма, ТекстПисьма)
    
    // 1. Получаем данные файла из базы
    ДанныеФайла = ПолучитьДанныеФайлаИзБазы(СсылкаНаФайл);
    Если ДанныеФайла.ДвоичныеДанные = Неопределено Тогда
        ВызватьИсключение "Не удалось получить двоичные данные файла из справочника.";
    КонецЕсли;
    
    // 2. Настраиваем профиль подключения
    Профиль = Новый ИнтернетПочтовыйПрофиль;
    Профиль.АдресСервераSMTP = "smtp.yandex.ru";
    Профиль.ПортSMTP = 465;
    Профиль.ИспользоватьSSLSMTP = Истина;
    Профиль.АутентификацияSMTP = СпособSMTPАутентификации.Login;
    Профиль.ПользовательSMTP = "my_mailbox@yandex.ru";
    Профиль.ПарольSMTP = "abcd-efgh-ijkl-mnop"; 
    Профиль.ВремяОжидания = 60;
    
    // 3. Формируем сообщение
    Сообщение = Новый ИнтернетПочтовоеСообщение;
    Сообщение.Отправитель.Адрес = "my_mailbox@yandex.ru";
    Сообщение.Отправитель.ОтображаемоеИмя = "Робот 1С";
    Сообщение.Получатели.Добавить(АдресПолучателя);
    Сообщение.Тема = ТемаПисьма;
    
    Сообщение.Тексты.Добавить(ТекстПисьма, ТипТекстаПочтовогоСообщения.ПростойТекст);
    
    // Добавляем вложение напрямую из оперативной памяти как двоичные данные
    Сообщение.Вложения.Добавить(ДанныеФайла.ДвоичныеДанные, ДанныеФайла.ИмяФайла);
    
    // 4. Подключаемся и отправляем
    Почта = Новый ИнтернетПочта;
    
    Попытка
        Почта.Подключиться(Профиль);
        Почта.Послать(Сообщение);
        Почта.Отключиться();
        Сообщить("Письмо успешно отправлено адресату " + АдресПолучателя);
    Исключение
        // Логируем ошибку и отключаем сессию в случае сбоя во время отправки
        Если Почта.Подключено() Тогда
            Почта.Отключиться();
        КонецЕсли;
        
        ЗаписьЖурналаРегистрации("ОтправкаПочты.ОшибкаОтправки",
            УровеньЖурналаРегистрации.Ошибка, , , 
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
            
        ВызватьИсключение "Не удалось отправить почтовое сообщение. Подробности смотрите в Журнале регистрации.";
    КонецПопытки;
    
КонецПроцедуры

Использование Библиотеки Стандартных Подсистем (БСП)

Если вы ведете разработку в современных типовых конфигурациях (таких как «1С:ERP», «1С:Комплексная автоматизация», «1С:Управление торговлей» или «1С:Бухгалтерия»), то писать низкоуровневый код работы с протоколом SMTP вручную не рекомендуется. Платформа 1С содержит встроенную подсистему работы с почтой в составе БСП.

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

Рассмотрим, как выглядит отправка письма с вложением через программный интерфейс БСП:


// Пример отправки письма средствами БСП
ПараметрыПисьма = Новый Структура;
ПараметрыПисьма.Вставить("Кому", "recipient@example.com");
ПараметрыПисьма.Вставить("Тема", "Документы по сделке");
ПараметрыПисьма.Вставить("Тело", "Добрый день! Во вложении файлы документов.");

// Подготавливаем массив вложений в формате БСП
МассивВложений = Новый Массив;

СтруктураВложения = Новый Структура;
СтруктураВложения.Вставить("Наименование", ДанныеФайла.ИмяФайла);
СтруктураВложения.Вставить("Данные", ДанныеФайла.ДвоичныеДанные); // Передаем ДвоичныеДанные

МассивВложений.Добавить(СтруктураВложения);
ПараметрыПисьма.Вставить("Вложения", МассивВложений);

// Получаем системную или предопределенную учетную запись почты в ИБ
УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.СистемнаяУчетнаяЗаписьЭлектроннойПочты;

// Вызываем стандартный метод отправки БСП
РаботаСПочтовымиСообщениями.ОтправитьПочтовоеСообщение(УчетнаяЗапись, ПараметрыПисьма);

Использование БСП является наиболее надежным, отказоустойчивым и предпочтительным методом разработки в современной экосистеме решений «1С:Предприятие 8».

← На главную