В практике разработки на платформе 1С:Предприятие 8.3 часто встречается ситуация: вы написали дополнительную обработку для рассылки уведомлений, протестировали её кнопкой "Выполнить" — всё работает идеально. Однако, как только вы настраиваете расписание в справочнике "Дополнительные отчеты и обработки", письма перестают приходить, хотя Журнал регистрации бодро рапортует об успешном завершении фонового задания. Проанализируем, почему так происходит, и как заставить код работать в серверном контексте.
Когда мы запускаем обработку вручную через интерфейс, код выполняется в контексте нашего текущего сеанса. Мы — авторизованные пользователи с определенным набором прав. Когда же обработка запускается по расписанию, создается фоновое задание. Оно выполняется на сервере под специальным системным пользователем (обычно это зарезервированный пользователь или учетная запись, под которой запущена служба кластера 1С).
В коде автора из сообщения 0 используется метод:
Учетки = РаботаСПочтовымиСообщениями.ДоступныеУчетныеЗаписи();
Проанализируем работу этого метода БСП. Он возвращает только те учетные записи электронной почты, на которые у текущего пользователя есть права доступа. Для фонового задания "текущий пользователь" может не иметь прав ни на одну учетную запись, либо список доступных ему записей будет совершенно иным. В итоге массив Учетки оказывается пустым или содержит не те данные, которые мы ожидаем.
Чтобы не гадать, почему письмо не уходит, нужно увидеть процесс "глазами" сервера. Рассмотрим, как настроить отладку для фонового задания:
-debug. Без этого отладчик просто не "зацепится" за серверные вызовы.ВыполнитьКоманду.Если фоновое задание пролетает слишком быстро и отладчик не успевает подключиться, проанализируем полезный прием: добавим в начало процедуры небольшую паузу.
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения = Неопределено) Экспорт
// Пауза для возможности подключения отладчиком
// (актуально для старых платформ, в новых достаточно настройки подключений)
// Ждать(10);
// ... дальнейший код
КонецПроцедуры
Обращение к учетной записи по индексу, как в примере Учетки[2].Ссылка, является крайне рискованным. Состав массива может меняться, и индекс 2 может указывать на разные записи или вовсе отсутствовать. Рассмотрим более надежные способы получения учетной записи.
Вариант А: Использование системной учетной записи. Для регламентных рассылок, которые не привязаны к конкретному сотруднику, лучше всего использовать предопределенную системную учетную запись.
УчетнаяЗапись = РаботаСПочтовымиСообщениями.СистемнаяУчетнаяЗапись();
Если УчетнаяЗапись.Пустая() Тогда
ЗаписьЖурналаРегистрации("РассылкаЗадолженности", УровеньЖурналаРегистрации.Ошибка, , , "Системная учетная запись не настроена!");
Возврат;
КонецЕсли;
Вариант Б: Поиск конкретной записи по наименованию. Если нам нужна специфическая почта, найдем её напрямую, минуя фильтры "доступности" для пользователя.
УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("Рассылка Роботом");
Если УчетнаяЗапись.Пустая() Тогда
// Обработка ошибки
КонецЕсли;
При регистрации внешней обработки в функции СведенияОВнешнейОбработке мы указываем параметр БезопасныйРежим.
ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
Проанализируем этот момент. Если установить Истина, платформа ограничит доступ обработки к "опасным" операциям, включая работу с интернетом и почтой. Для рассылок всегда устанавливаем Ложь. Также убедимся, что у профиля безопасности (если они используются в базе) есть разрешения на работу с внешними ресурсами.
Выясним причину, связанную с сетевым окружением. Даже если код идеален, сервер приложений 1С может находиться в другом сегменте сети, нежели ваш компьютер. Разберем типичные проблемы:
rphost.exe.inetcfg.xml на стороне сервера.Чтобы понимать, что происходит "за кулисами" регламентного задания, всегда оборачивайте критические участки в блок попытки. Рассмотрим правильную структуру процедуры выполнения:
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения = Неопределено) Экспорт
Попытка
Письмо = Новый ИнтернетПочтовоеСообщение;
Письмо.Тема = "Тест задолженности";
Письмо.Тексты.Добавить("Содержимое письма...");
Письмо.Получатели.Добавить("user@example.com");
// Получаем конкретную учетную запись
УчетнаяЗапись = Справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("ОсновнаяПочта");
Если УчетнаяЗапись.Пустая() Тогда
ВызватьИсключение "Не найдена учетная запись 'ОсновнаяПочта'";
КонецЕсли;
РаботаСПочтовымиСообщениями.ОтправитьПисьмо(УчетнаяЗапись, Письмо);
ЗаписьЖурналаРегистрации("РассылкаЗадолженности", УровеньЖурналаРегистрации.Информация, , , "Письмо успешно отправлено.");
Исключение
// Записываем подробности ошибки в Журнал регистрации
ТекстОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("РассылкаЗадолженности", УровеньЖурналаРегистрации.Ошибка, , , "Ошибка при отправке: " + ТекстОшибки);
КонецПопытки;
КонецПроцедуры
Подведем итоги: Основная проблема автора темы заключалась в использовании метода ДоступныеУчетныеЗаписи(), который в контексте фонового задания возвращал пустой массив из-за отсутствия прав у системного сеанса. Проанализировав ситуацию, мы пришли к выводу, что для стабильной работы регламентных заданий следует использовать либо СистемнаяУчетнаяЗапись(), либо прямой поиск по справочнику, а также обязательно логировать ошибки в Журнал регистрации.