Как отправить печатную форму по электронной почте в формате PDF без сохранения на диск в 1С

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

При автоматизации бизнес-процессов часто возникает задача программной отправки печатных форм (счетов, актов, накладных) по электронной почте. Стандартный подход с сохранением файла на диск и последующим его прикреплением к письму часто приводит к засорению сервера временными файлами или возникновению ошибок доступа («Файл занят другим процессом»). В этой статье мы подробно разберем, как решить эту задачу максимально элегантно, используя современные возможности платформы 1С:Предприятие 8.3.

Метод 1. Использование двоичных данных (Рекомендуемый способ)

Начиная с версии платформы 8.3.10, объект ИнтернетПочтовоеВложение позволяет добавлять данные напрямую из оперативной памяти, используя объект ДвоичныеДанные. Это «золотой стандарт», который полностью исключает работу с файловой системой и снимает все вопросы о правах доступа к папкам или блокировках файлов.

Рассмотрим по шагам, как реализовать этот алгоритм:

  1. Сформируем печатную форму в объект ТабличныйДокумент.
  2. Сконвертируем её в двоичные данные формата PDF.
  3. Добавим полученные данные во вложения письма.

Проанализируем пример кода:


// 1. Получаем печатную форму (например, из менеджера документа)
ТабДок = Документы.СчетНаОплатуПокупателю.ПечатьСчета(СсылкаНаОбъект);

// 2. Преобразуем табличный документ в двоичные данные PDF напрямую в памяти
ДанныеPDF = ТабДок.ПолучитьДвоичныеДанные(ТипФайлаТабличногоДокумента.PDF);

// 3. Создаем почтовое сообщение
Сообщение = Новый ИнтернетПочтовоеСообщение;
Сообщение.Получатели.Добавить("client@example.com");
Сообщение.Тема = "Счет на оплату №" + СсылкаНаОбъект.Номер;
Сообщение.Тексты.Добавить("Добрый день! Во вложении ваш счет.", ТипТекстаПочтовогоСообщения.ПростойТекст);

// 4. Добавляем двоичные данные как вложение
// Первый параметр - сами данные, второй - имя файла, которое увидит клиент
Сообщение.Вложения.Добавить(ДанныеPDF, "Schet_" + СсылкаНаОбъект.Номер + ".pdf");

// 5. Отправка через почтовый профиль
Почта = Новый ИнтернетПочта;
Почта.Подключиться(Профиль);
Почта.Послать(Сообщение);
Почта.Отключиться();

Этот метод не требует очистки временных каталогов и работает максимально быстро, так как все операции происходят в оперативной памяти сервера.

Метод 2. Работа через потоки (MemoryStream)

Иногда требуется более тонкая работа с данными, например, если вы используете промежуточные буферы или специфические методы обработки. В 1С для этих целей предназначен объект ПотокВПамяти. Однако разработчики часто сталкиваются с проблемой, когда сформированный PDF оказывается «пустым» (0 байт).

Выясним причину этой ошибки. Когда мы записываем ТабличныйДокумент в поток с помощью метода Записать(), внутренний указатель потока перемещается в самый конец (на последнюю позицию записанных данных). Если сразу после этого попытаться прочитать данные из потока, система начнет чтение с текущей позиции указателя, где уже ничего нет.

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


Поток = Новый ПотокВПамяти();
// Записываем печатную форму в поток
ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.PDF);

// КРИТИЧЕСКИ ВАЖНО: Сбрасываем позицию указателя в начало потока
Поток.Перейти(0, ПозицияВПотоке.Начало);

// Теперь можно получить двоичные данные
ДанныеДляПисьма = Поток.ПолучитьДвоичныеДанные();
Сообщение.Вложения.Добавить(ДанныеДляПисьма, "Document.pdf");
Поток.Закрыть();

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

Метод 3. Использование временных файлов и решение проблемы блокировки

Если по каким-то причинам вы используете старые версии платформы (ниже 8.3.10) или архитектура решения требует наличия физического файла, необходимо правильно обрабатывать жизненный цикл временного объекта. Как было замечено в обсуждении, основной проблемой является ошибка «Файл занят другой программой» при попытке удаления файла методом УдалитьФайлы() сразу после отправки.

Разберем ситуацию: объект ИнтернетПочтовоеСообщение хранит ссылку на файл в своей коллекции Вложения. Пока этот объект существует в памяти, операционная система считает файл заблокированным процессом 1С. Чтобы «отпустить» файл, нужно либо дождаться удаления объекта сообщения из памяти, либо принудительно очистить коллекцию.

Рассмотрим правильный алгоритм работы с временным файлом:


ИмяФайла = ПолучитьИмяВременногоФайла("pdf");
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.PDF);

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

// Выполняем отправку
Почта = Новый ИнтернетПочта;
Почта.Подключиться(Профиль);
Почта.Послать(Сообщение);
Почта.Отключиться();

// Чтобы файл удалился, необходимо очистить вложения или уничтожить объект сообщения
Сообщение.Вложения.Очистить(); 

Попытка
    УдалитьФайлы(ИмяФайла);
Исключение
    // Если файл всё еще занят, можно оставить его для автоматической очистки системой
КонецПопытки;

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

Особенности работы на сервере (Linux)

Проанализируем важный нюанс: если ваш сервер 1С работает под управлением операционной системы Linux, метод Записать() для формирования PDF может выдать ошибку или сформировать документ с некорректным отображением шрифтов (например, «квадратики» или иероглифы). Это происходит из-за отсутствия стандартных Windows-шрифтов (Arial, Times New Roman), которые по умолчанию используются в макетах 1С.

Для решения этой проблемы на сервере Linux необходимо установить пакет шрифтов Microsoft. Например, для Ubuntu/Debian команда будет выглядеть так: sudo apt-get install ttf-mscorefonts-installer. После установки шрифтов рекомендуется перезапустить службу сервера 1С.

Рекомендации по производительности

При выборе между сохранением на диск и использованием оперативной памяти (двоичных данных), руководствуйтесь следующими правилами:

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

← На главную