Как очистить временные файлы при массовой отправке почты в 1С?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

При реализации массовой рассылки писем с вложениями средствами платформы 1С:Предприятие разработчики нередко сталкиваются с ситуацией, когда свободное место на системном диске стремительно заканчивается. В каталоге временных файлов пользователя (Temp) формируются многочисленные папки вида tmp___.tmp с копиями вложений, которые могут занимать десятки гигабайт за несколько часов непрерывной работы. При этом вызовы стандартных методов очистки вложений не приводят к освобождению дискового пространства до полного перезапуска клиентского приложения. Разберем причины такого поведения платформы и детально рассмотрим способы решения данной задачи.

Почему 1С блокирует и не удаляет временные файлы

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

  1. В системном каталоге временных файлов создается вложенная папка с уникальным именем, куда выгружается сформированный пакет вложения.
  2. Процесс 1С удерживает открытые файловые дескрипторы для созданных временных структур вплоть до уничтожения объекта или завершения сеанса.
  3. Методы Сообщение.Вложения.Очистить() или Сообщение.Вложения.Удалить() очищают коллекцию элементов только в объектной модели встроенного языка, но не удаляют низкоуровневые файлы с диска немедленно.
  4. В результате при отправке тысяч писем в рамках одного сеанса все временные папки накапливаются в каталоге Temp, блокируя гигабайты дисковой памяти.

Способ 1. Выполнение рассылки пакетами через фоновые задания

Рассмотрим наиболее надежный и архитектурно правильный способ решения проблемы при разработке на платформе 1С:Предприятие 8.3. Идея заключается в разделении общего массива писем на небольшие пачки (например, по 20–50 писем) и выполнении отправки каждого пакета в отдельном фоновом задании.

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

Посмотрим на пример организации пакетного запуска:


// Основной цикл разделения массива на порции
РазмерПакета = 30;
ТекущийПакет = Новый Массив;

Для Каждого ЭлементРассылки Из СписокПолучателей Цикл
    ТекущийПакет.Добавить(ЭлементРассылки);
    
    Если ТекущийПакет.Количество() >= РазмерПакета Тогда
        ПараметрыЗадания = Новый Массив;
        ПараметрыЗадания.Добавить(ТекущийПакет);
        
        // Запуск фонового задания на сервере
        Задание = ФоновыеЗадания.Выполнить("МодульРассылки.ОтправитьПакетПисем", ПараметрыЗадания);
        Задание.ОжидатьЗавершения();
        
        ТекущийПакет = Новый Массив;
    КонецЕсли;
КонецЦикла;

// Отправка оставшихся элементов
Если ТекущийПакет.Количество() > 0 Тогда
    ПараметрыЗадания = Новый Массив;
    ПараметрыЗадания.Добавить(ТекущийПакет);
    Задание = ФоновыеЗадания.Выполнить("МодульРассылки.ОтправитьПакетПисем", ПараметрыЗадания);
    Задание.ОжидатьЗавершения();
КонецЕсли;

Способ 2. Принудительная очистка временных папок по маске во время работы

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

Рассмотрим реализацию процедуры периодической очистки:


Процедура ОчиститьВременныеПапкиПочты()
    КаталогТемп = КаталогВременныхФайлов();
    
    // Поиск временных папок платформы
    МассивПапок = НайтиФайлы(КаталогТемп, "tmp*.tmp");
    Для Каждого НайденнаяПапка Из МассивПапок Цикл
        Если НайденнаяПапка.ЭтоКаталог() Тогда
            Попытка
                УдалитьФайлы(НайденнаяПапка.ПолноеИмя);
            Исключение
                // Папка в данный момент заблокирована процессом отправки - пропускаем
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Вызывать данную процедуру рекомендуется через определенные интервалы, например, после каждых 10–20 отправленных сообщений.

Способ 3. Контроль жизненного цикла объектов и явное обнуление переменных

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

Посмотрим на пример кода с корректным управлением памятью:


Процедура ОтправитьОдноСообщение(Профиль, АдресПолучателя, Тема, Текст, ПутьКВложению, ИмяФайлаВложения)
    Почта = Новый ИнтернетПочта;
    Сообщение = Новый ИнтернетПочтовоеСообщение;
    
    Сообщение.Получатели.Добавить(АдресПолучателя);
    Сообщение.Тема = Тема;
    Сообщение.Тексты.Добавить(Текст, ТипТекстаПочтовогоСообщения.ПростойТекст);
    
    // Добавление вложения из предварительно сохраненного файла
    Сообщение.Вложения.Добавить(ПутьКВложению, ИмяФайлаВложения);
    
    Попытка
        Почта.Подключиться(Профиль);
        Почта.Послать(Сообщение);
        Почта.Отключиться();
    Исключение
        Попытка
            Почта.Отключиться();
        Исключение
        КонецПопытки;
        ВызватьИсключение;
    КонецПопытки;
    
    // Явное освобождение ссылок для сборщика мусора
    Сообщение = Неопределено;
    Почта = Неопределено;
    
    // Удаление исходного файла вложения
    Попытка
        УдалитьФайлы(ПутьКВложению);
    Исключение
    КонецПопытки;
КонецПроцедуры

Способ 4. Переопределение системных переменных среды и использование RAM-диска

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

  1. Перенос каталога временных файлов на дополнительный диск: через свойства операционной системы (переменные среды TEMP и TMP) или в скрипте запуска сеанса можно переопределить путь к временной папке, перенаправив ее с системного диска C: на более емкий накопитель (например, D:\1C_Temp).
  2. Использование виртуального RAM-диска: выделение части оперативной памяти под быстрый RAM-диск с размещением на нем папки Temp исключает износ SSD-накопителей и автоматически очищает все временные файлы при перезапуске сервера или рабочей станции.

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

← На главную