При разработке механизмов автоматической рассылки отчетов или уведомлений программисты часто сталкиваются с тем, что во время работы регламентного задания интерфейс пользователя «замирает», появляется «колесико» ожидания, и работа в программе становится невозможной. Особенно остро эта проблема проявляется в конфигурациях на обычных формах, таких как Управление производственным предприятием (УПП) 1.3. Разберем детально, почему это происходит и как настроить систему так, чтобы отправка сообщений никак не влияла на комфорт пользователей.
Первое, на что стоит обратить внимание при анализе ситуации — это режим работы базы данных. В системе 1С:Предприятие 8 механизмы выполнения фоновых и регламентных заданий принципиально отличаются в зависимости от архитектуры:
Проанализируем ситуацию: если вы используете файловую базу, то простое создание регламентного задания не гарантирует его «невидимость». Чтобы решить проблему в файловом варианте, необходимо выделить отдельный сеанс, который будет заниматься исключительно выполнением задач. Это можно сделать, запустив программу с параметром /DoScheduledJobs или используя специальную обработку, вызывающую метод ВыполнитьОбработкуЗаданий() в бесконечном цикле.
Часто причиной «подлагиваний» становится неоптимальный код. Посмотрим на типовой пример, где соединение с почтовым сервером устанавливается внутри цикла перебора писем. Это в корне неверно, так как операция Подключиться() требует времени на установку TCP-соединения, SSL-рукопожатие и авторизацию (иногда до 2-5 секунд на каждое письмо).
Рассмотрим правильную структуру процедуры рассылки. Мы должны вынести установку соединения за пределы цикла, отправить все письма в рамках одной сессии и только потом закрыть соединение. Проанализируем пример оптимизированного кода:
Процедура ВыполнитьРассылкуИзОчереди() Экспорт
// Получаем сообщения из регистра сведений (очереди)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Очередь.Получатель,
| Очередь.АдресЭлектроннойПочты,
| Очередь.ПутьКФайлу
|ИЗ
| РегистрСведений.ОчередьРассылки КАК Очередь";
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Настраиваем профиль один раз
Профиль = Новый ИнтернетПочтовыйПрофиль;
Профиль.АдресСервераSMTP = "smtp.yandex.ru";
Профиль.ПортSMTP = 465;
Профиль.ИспользоватьSSLSMTP = Истина;
Профиль.ПользовательSMTP = "info@company.ru";
Профиль.ПарольSMTP = "ваш_пароль_приложения"; // Важно: используйте пароли приложений!
Профиль.АутентификацияSMTP = СпособSMTPАутентификации.Login;
Почта = Новый ИнтернетПочта;
Попытка
Почта.Подключиться(Профиль);
Исключение
ЗаписьЖурналаРегистрации("Рассылка", УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка подключения: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Пока Выборка.Следующий() Цикл
Письмо = Новый ИнтернетПочтовоеСообщение;
Письмо.Тема = "Ваш отчет";
Письмо.Отправитель = Профиль.ПользовательSMTP;
Письмо.Получатели.Добавить(Выборка.АдресЭлектроннойПочты);
// Проверяем наличие файла перед вложением
Файл = Новый Файл(Выборка.ПутьКФайлу);
Если Файл.Существует() Тогда
Письмо.Вложения.Добавить(Выборка.ПутьКФайлу);
КонецЕсли;
Попытка
Почта.Послать(Письмо);
// После успешной отправки удаляем из очереди
УдалитьЗаписьИзОчереди(Выборка.Получатель);
Исключение
ЗаписьЖурналаРегистрации("Рассылка", УровеньЖурналаРегистрации.Предупреждение, , ,
"Не удалось отправить письмо для " + Выборка.Получатель + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
Почта.Отключиться();
КонецПроцедуры
Выясним причину кратковременных замираний даже в серверном режиме. Если ваше регламентное задание после отправки каждого письма открывает транзакцию для удаления записи из РегистрСведений, это может блокировать таблицу для других пользователей.
Рекомендуется: накопить массив отправленных идентификаторов и удалить их одной операцией после завершения цикла, либо выполнять удаление вне основной транзакции. Также важно помнить, что в фоновых заданиях нельзя использовать методы Сообщить(), так как они ориентированы на интерактивный интерфейс. Используйте ЗаписьЖурналаРегистрации() для логирования процесса.
Проанализируем ситуацию с почтовыми серверами (Yandex, Mail.ru, Gmail). В последнее время они запретили авторизацию по обычному паролю от ящика для сторонних приложений. Если ваша 1С не может подключиться, проверьте следующие пункты:
ИспользоватьSSLSMTP на старых версиях Windows может потребоваться обновление компонентов системы или платформы 1С для поддержки TLS 1.2.Прежде чем писать свою подсистему рассылки с нуля, разберем возможности встроенного функционала. В конфигурации Управление производственным предприятием существует справочник УчетныеЗаписиЭлектроннойПочты и механизмы рассылки отчетов.
Использование встроенных функций УправлениеЭлектроннойПочтой.ОтправитьПочтовоеСообщение() позволяет избежать многих ошибок ручного кодинга, так как в типовом коде уже предусмотрены обработки исключений и настройки таймаутов. Если ваша задача — рассылка расчетных листков, лучше доработать типовой механизм рассылки, который корректно работает в фоновом режиме через ФоновыеЗадания.
Подведем итог: для исключения «зависаний» в файловой базе — выделите отдельный технический сеанс для задач. Для серверной базы — оптимизируйте код, вынося подключение к SMTP за цикл и минимизируя блокировки базы данных при обновлении очереди сообщений.