Почему внешняя обработка 1С работает при ручном запуске, но не отправляет почту как регламентное задание?

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

В практике разработки на платформе 1С:Предприятие 8.3 часто встречается ситуация: вы написали дополнительную обработку для рассылки уведомлений, протестировали её кнопкой "Выполнить" — всё работает идеально. Однако, как только вы настраиваете расписание в справочнике "Дополнительные отчеты и обработки", письма перестают приходить, хотя Журнал регистрации бодро рапортует об успешном завершении фонового задания. Проанализируем, почему так происходит, и как заставить код работать в серверном контексте.

Разбираем причины: Разница контекстов выполнения

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

В коде автора из сообщения 0 используется метод: Учетки = РаботаСПочтовымиСообщениями.ДоступныеУчетныеЗаписи(); Проанализируем работу этого метода БСП. Он возвращает только те учетные записи электронной почты, на которые у текущего пользователя есть права доступа. Для фонового задания "текущий пользователь" может не иметь прав ни на одну учетную запись, либо список доступных ему записей будет совершенно иным. В итоге массив Учетки оказывается пустым или содержит не те данные, которые мы ожидаем.

Шаг 1: Правильная отладка фонового задания

Чтобы не гадать, почему письмо не уходит, нужно увидеть процесс "глазами" сервера. Рассмотрим, как настроить отладку для фонового задания:

  1. Разрешение отладки на сервере: Убедимся, что сервер 1С запущен с ключом -debug. Без этого отладчик просто не "зацепится" за серверные вызовы.
  2. Настройка подключения: В конфигураторе перейдем в меню Отладка -> Подключения. Нажмем кнопку "Настройка" и установим флажок "Фоновые задания".
  3. Точка останова: Поставим точку останова в процедуре ВыполнитьКоманду.
  4. Запуск: Чтобы не ждать расписания, используем консоль заданий или просто перенастроим расписание на ближайшую минуту.

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


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения = Неопределено) Экспорт
    // Пауза для возможности подключения отладчиком
    // (актуально для старых платформ, в новых достаточно настройки подключений)
    // Ждать(10); 
    
    // ... дальнейший код
КонецПроцедуры

Шаг 2: Исправляем работу с учетными записями

Обращение к учетной записи по индексу, как в примере Учетки[2].Ссылка, является крайне рискованным. Состав массива может меняться, и индекс 2 может указывать на разные записи или вовсе отсутствовать. Рассмотрим более надежные способы получения учетной записи.

Вариант А: Использование системной учетной записи. Для регламентных рассылок, которые не привязаны к конкретному сотруднику, лучше всего использовать предопределенную системную учетную запись.


УчетнаяЗапись = РаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись();
Если УчетнаяЗапись.Пустая() Тогда
    ЗаписьЖурналаРегистрации("РассылкаЗадолженности", УровеньЖурналаРегистрации.Ошибка, , , "Системная учетная запись не настроена!");
    Возврат;
КонецЕсли;

Вариант Б: Поиск конкретной записи по наименованию. Если нам нужна специфическая почта, найдем её напрямую, минуя фильтры "доступности" для пользователя.


УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("Рассылка Роботом");
Если УчетнаяЗапись.Пустая() Тогда
    // Обработка ошибки
КонецЕсли;

Шаг 3: Проверка безопасного режима и прав

При регистрации внешней обработки в функции СведенияОВнешнейОбработке мы указываем параметр БезопасныйРежим. ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь); Проанализируем этот момент. Если установить Истина, платформа ограничит доступ обработки к "опасным" операциям, включая работу с интернетом и почтой. Для рассылок всегда устанавливаем Ложь. Также убедимся, что у профиля безопасности (если они используются в базе) есть разрешения на работу с внешними ресурсами.

Шаг 4: Сетевые ограничения сервера

Выясним причину, связанную с сетевым окружением. Даже если код идеален, сервер приложений 1С может находиться в другом сегменте сети, нежели ваш компьютер. Разберем типичные проблемы:

  1. Брандмауэр: Порты 25, 465 или 587 могут быть открыты на рабочей станции программиста, но закрыты на самом сервере 1С.
  2. Антивирус: Программное обеспечение на сервере может блокировать исходящие SMTP-соединения от процесса rphost.exe.
  3. Прокси-сервер: Если выход в интернет осуществляется через прокси, настройки в вашем 1С-предприятии (клиенте) могут отличаться от настроек системной учетной записи на сервере. Проверьте файл inetcfg.xml на стороне сервера.

Шаг 5: Надежная обработка ошибок

Чтобы понимать, что происходит "за кулисами" регламентного задания, всегда оборачивайте критические участки в блок попытки. Рассмотрим правильную структуру процедуры выполнения:


Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения = Неопределено) Экспорт
    
    Попытка
        Письмо = Новый ИнтернетПочтовоеСообщение;
        Письмо.Тема = "Тест задолженности";
        Письмо.Тексты.Добавить("Содержимое письма...");
        Письмо.Получатели.Добавить("user@example.com");
        
        // Получаем конкретную учетную запись
        УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("ОсновнаяПочта");
        
        Если УчетнаяЗапись.Пустая() Тогда
             ВызватьИсключение "Не найдена учетная запись 'ОсновнаяПочта'";
        КонецЕсли;
        
        РаботаСПочтовымиСообщениями.ОтправитьПисьмо(УчетнаяЗапись, Письмо);
        
        ЗаписьЖурналаРегистрации("РассылкаЗадолженности", УровеньЖурналаРегистрации.Информация, , , "Письмо успешно отправлено.");
        
    Исключение
        // Записываем подробности ошибки в Журнал регистрации
        ТекстОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
        ЗаписьЖурналаРегистрации("РассылкаЗадолженности", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка при отправке: " + ТекстОшибки);
    КонецПопытки;
    
КонецПроцедуры

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

← На главную