Рассылка отчетов и уведомлений по электронной почте — стандартная задача для любой корпоративной информационной системы. В конфигурации «1С:Управление производственным предприятием 1.3» (УПП 1.3) эта задача легко реализуется при интерактивной работе пользователя. Однако при попытке перенести этот функционал на уровень сервера для автоматического выполнения в регламентном задании разработчики часто сталкиваются с неочевидными трудностями. Программа либо выдает ошибку о недоступности методов, либо отрабатывает без ошибок, но фактически письма до адресатов не доходят.
В этой статье мы подробно разберем, почему возникает такое поведение, проанализируем внутренние механизмы почтовой подсистемы УПП 1.3 и выработаем надежное архитектурное решение для автоматической рассылки сообщений.
Проанализируем первую частую ошибку, с которой сталкивается разработчик при переносе кода из внешней обработки в модуль регламентного задания. На клиенте вызов отправки отрабатывает без нареканий, но в фоновом задании система выдает исключение: Метод объекта не обнаружен (Отправить письмо). При этом сам документ успешно записывается в информационную базу.
Выясним причину этой ошибки. Регламентное задание всегда выполняется на сервере приложений 1С:Предприятие в неинтерактивном режиме. В этом контексте полностью отсутствует клиентское окружение. Если в коде используется вызов функций из модулей форм, клиентских общих модулей или интерактивных команд (например, симуляция нажатия кнопки «Отправить» на форме документа), серверный процесс просто не сможет обнаружить эти методы.
Для решения этой проблемы необходимо полностью исключить клиентский контекст и использовать специализированные серверные программные интерфейсы. В типовой конфигурации УПП 1.3 за отправку почты отвечает общий модуль УправлениеЭлектроннымиПисьмами. Вместо вызова клиентских процедур мы должны использовать серверный метод ОтправитьПисьма().
Рассмотрим пример правильного вызова процедуры отправки писем на сервере:
// Вызов стандартного серверного метода для отправки подготовленной почты
ПользовательОтправки = ПараметрыСеанса.ТекущийПользователь;
МассивПисем = Новый Массив;
МассивПисем.Добавить(СсылкаНаСозданноеПисьмо);
УправлениеЭлектроннымиПисьмами.ОтправитьПисьма(МассивПисем, ПользовательОтправки);
Перейдем ко второй проблеме, которая часто ставит разработчиков в тупик: код выполняется без ошибок, транзакция завершается успешно, документ ЭлектронноеПисьмо создается и записывается в базу данных, но реальной отправки на почтовый ящик получателя не происходит. При этом, если зайти в созданный документ вручную под тем же пользователем и нажать кнопку «Отправить», письмо мгновенно уходит адресату.
Разберем по шагам логику работы серверной процедуры УправлениеЭлектроннымиПисьмами.ОтправитьПисьма(). Данный метод предназначен для групповой обработки очереди исходящих сообщений. Он сканирует переданные ему документы и обрабатывает только те из них, которые готовы к отправке.
Основным критерием готовности является реквизит документа СтатусПисьма. Если вы программно создаете документ и просто записываете его, по умолчанию ему присваивается статус из перечисления — Черновик (или поле остается незаполненным). Метод отправки просто игнорирует такие документы, считая их незавершенными черновиками пользователя. При этом никаких ошибок в журнал регистрации не записывается — система считает, что все идет штатно.
Чтобы исправить это поведение, перед записью документа в коде регламентного задания необходимо явно перевести его в статус готовности к отправке:
ПисьмоОбъект = Документы.ЭлектронноеПисьмо.СоздатьДокумент();
// Заполнение основных реквизитов (Тема, Текст, Получатели)
// ...
// Обязательная установка статуса перед отправкой
ПисьмоОбъект.СтатусПисьма = Перечисления.СтатусыПисем.Исходящее;
ПисьмоОбъект.Записать();
Еще один важный нюанс работы почтовой подсистемы УПП 1.3 — ее сильная зависимость от текущего пользователя. Многие механизмы конфигурации используют глобальную переменную глТекущийПользователь или вызовы вроде глЗначениеПеременной("глТекущийПользователь") для определения настроек учетных записей и прав доступа.
В сессии регламентного задания, выполняющейся на сервере в фоновом режиме, глобальный контекст клиента не инициализирован. Попытка получить значение текущего пользователя через глобальные переменные вернет Неопределено или вызовет тихую ошибку в коде отправки, которая перехватывается конструкцией Попытка...Исключение внутри типового кода конфигурации.
Чтобы избежать подобных сбоев, проанализируем следующие рекомендации:
УчетнаяЗапись), не полагаясь на то, что система определит «учетную запись по умолчанию» для текущего пользователя.Пользователи отдельного служебного пользователя (например, «РоботРассылок») и настроить регламентное задание так, чтобы оно выполнялось под его учетными данными.УправлениеЭлектроннымиПисьмами.В 1С:УПП 1.3 учетные записи электронной почты делятся на «Персональные» и «Общие». Если для отправки отчетов в регламентном задании вы используете персональную учетную запись конкретного сотрудника, система может заблокировать отправку.
Когда регламентное задание запускается на сервере, оно выполняется от имени пользователя, указанного в настройках этого задания (или под системным пользователем по умолчанию). Если у этого пользователя нет прав на чтение и использование персональной учетной записи отправителя, отправка завершится ошибкой доступа на уровне RLS (ограничение прав на уровне записей) или на уровне бизнес-логики почтового модуля.
Решение: Создайте специальную общую (системную) учетную запись электронной почты для рассылок (например, noreply@company.com). В настройках этой учетной записи в 1С обязательно предоставьте права на ее использование тому служебному пользователю, под которым выполняется регламентное задание.
Если все программные настройки выполнены верно, но письма все равно не уходят, необходимо проанализировать сетевую инфраструктуру. Тот факт, что «вручную с компьютера пользователя письма уходят на ура», гарантирует только то, что сетевые порты открыты на рабочей станции конкретного сотрудника.
Регламентное задание выполняется непосредственно сервером приложений 1С (процесс rphost.exe). Очень часто серверный компьютер находится в изолированном сегменте сети или в закрытом контуре безопасности, где действуют строгие правила фильтрации трафика:
usr1cv8, в Linux — 1cv8) может не иметь прав на выход во внешнюю сеть или требовать специальной настройки системного прокси-сервера.Для диагностики этой проблемы выполните трассировку сетевых портов непосредственно с сервера, на котором запущен 1С:Предприятие, до почтового сервера, указанного в учетной записи 1С.
Попытка выполнить отправку почты (SMTP-сессию) непосредственно внутри транзакции формирования отчета в вашем регламентном задании — это архитектурно неверный подход. Сетевые задержки, временная недоступность почтового сервера или ошибки авторизации могут привести к зависанию фонового задания или его аварийному завершению.
Правильнее всего использовать разделение процессов по схеме «Очередь сообщений». Разберем этот подход по шагам:
Шаг 1. Формирование и подготовка сообщения
В вашем кастомном регламентном задании вы только подготавливаете данные. Вы формируете отчет, конвертируете его в двоичные данные (например, в формат PDF или XLSX), создаете документ ЭлектронноеПисьмо, прикрепляете вложение, заполняете получателей, устанавливаете статус Исходящее и просто записываете документ в базу.
Рассмотрим пример кода для подготовки сообщения:
// Создание документа
Письмо = Документы.ЭлектронноеПисьмо.СоздатьДокумент();
Письмо.Дата = ТекущаяДата();
Письмо.Тема = "Ежедневный отчет по продажам";
Письмо.УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("СистемнаяПочта");
// Добавление получателя
НовыйПолучатель = Письмо.Получатели.Добавить();
НовыйПолучатель.АдресЭлектроннойПочты = "manager@company.com";
НовыйПолучатель.Представление = "Руководитель отдела продаж";
// Добавление вложения
НовоеВложение = Письмо.Вложения.Добавить();
НовоеВложение.ИмяФайла = "Отчет.xlsx";
НовоеВложение.Объект = Новый ХранилищеЗначения(ДвоичныеДанныеОтчета);
// Установка статуса готовности к отправке
Письмо.СтатусПисьма = Перечисления.СтатусыПисем.Исходящее;
Письмо.Записать();
Шаг 2. Отправка писем стандартным механизмом
Не вызывайте методы отправки внутри вашего кода. Вместо этого задействуйте стандартное типовое регламентное задание «Получение и отправка электронных писем» (или «Отправка электронных сообщений»), которое уже встроено в УПП 1.3. Настройте его расписание на периодический запуск (например, каждые 5-10 минут).
Это задание автоматически найдет в базе данных все документы ЭлектронноеПисьмо со статусом Исходящее, корректно инициализирует все необходимые серверные переменные окружения, распределит нагрузку и отправит сообщения получателям, изменив их статус на Отправленное в случае успеха.
Такой подход гарантирует стабильность работы системы: если почтовый сервер будет временно недоступен, ваши отчеты не пропадут — они просто останутся в базе со статусом Исходящее и уйдут при следующем сеансе работы стандартного регламентного задания, когда связь восстановится.