Как реализовать отправку уведомлений по электронной почте при появлении новых записей в регистре сведений

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

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

Архитектурный подход: Подписки на события или Регламентные задания

Перед тем как приступить к написанию кода, проанализируем, какой механизм запуска лучше использовать. Существует два основных способа:

  1. Подписки на события (событийный подход): Мы можем использовать событие ПриЗаписи набора записей регистра. Это позволяет отправлять уведомление мгновенно. Однако, если записей много, это может замедлить работу пользователя, так как транзакция записи будет ждать завершения процесса отправки почты.
  2. Регламентные задания (опросный подход): Программа по расписанию (например, раз в 10 минут) проверяет наличие новых записей. Это наиболее безопасный метод для производительности системы, который мы и рассмотрим подробнее.

Шаг 1. Определение «новости» записей в регистре

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

Разберем, как должен выглядеть запрос для получения данных, которые еще не были обработаны системой уведомлений:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	МП_ОчередьЧеков.ЧекККМ.Дата КАК Дата,
    |	МП_ОчередьЧеков.ЧекККМ.Номер КАК Номер,
    |	МП_ОчередьЧеков.ЧекККМ.Магазин КАК Магазин,
    |	МП_ОчередьЧеков.ЧекККМ.Ответственный КАК Ответственный
    |ИЗ
    |	РегистрСведений.МП_ОчередьЧеков КАК МП_ОчередьЧеков
    |ГДЕ
    |	МП_ОчередьЧеков.УведомлениеОтправлено = ЛОЖЬ";

РезультатЗапроса = Запрос.Выполнить();

Шаг 2. Корректный обход выборки и формирование текста письма

Проанализируем типичную проблему, с которой сталкиваются разработчики: при обходе коллекции в переменную ТелоПисьма попадает только последняя запись. Это происходит из-за перезаписи значения переменной вместо его накопления. Выясним, как правильно собрать все данные в одну строку.

Рассмотрим правильный алгоритм накопления текста в цикле Пока Выборка.Следующий():


Выборка = РезультатЗапроса.Выбрать();

ТекстПисьма = "Список чеков, требующих внимания:" + Символы.ПС;
КоличествоЗаписей = 0;

Пока Выборка.Следующий() Цикл
    // Накапливаем строки, добавляя текущие данные к уже существующим
    ТекстПисьма = ТекстПисьма + "Чек № " + Выборка.Номер + " от " + Формат(Выборка.Дата, "ДЛФ=DT") + 
                  " (Магазин: " + Выборка.Магазин + ")" + Символы.ПС;
    КоличествоЗаписей = КоличествоЗаписей + 1;
    
    // Здесь же можно помечать записи как отправленные (если используется объектная техника)
    // Либо собрать ссылки в массив для массового обновления после цикла
КонецЦикла;

ТекстПисьма = ТекстПисьма + Символы.ПС + "Всего записей: " + КоличествоЗаписей;

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

Шаг 3. Реализация отправки через ИнтернетПочта (без БСП)

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

Посмотрим на пример функции отправки, учитывающей современные требования почтовых серверов (SSL и авторизация):


&НаСервере
Процедура ОтправитьУведомление(АдресПолучателя, Тема, Тело)
    
    Профиль = Новый ИнтернетПочтовыйПрофиль;
    Профиль.АдресСервераSMTP = "smtp.yandex.ru"; // Укажите ваш сервер
    Профиль.ПортSMTP = 465;
    Профиль.ИспользоватьSSLSMTP = Истина;
    Профиль.ПользовательSMTP = "robot@yourcompany.ru";
    Профиль.ПарольSMTP = "vash_parol_prilozheniya"; // Используйте специальные пароли приложений!
    Профиль.АутентификацияSMTP = СпособSMTPАутентификации.Login;
    
    Сообщение = Новый ИнтернетПочтовоеСообщение;
    Сообщение.Отправитель.Адрес = "robot@yourcompany.ru";
    Сообщение.Отправитель.ОтображаемоеИмя = "Робот 1С:Розница";
    Сообщение.Тема = Тема;
    Сообщение.Получатели.Добавить(АдресПолучателя);
    
    // Добавляем текст
    Сообщение.Тексты.Добавить(Тело, ТипТекстаПочтовогоСообщения.ПростойТекст);
    
    Почта = Новый ИнтернетПочта;
    Попытка
        Почта.Подключиться(Профиль);
        Почта.Послать(Сообщение);
        Почта.Отключиться();
    Исключение
        ЗаписьЖурналаРегистрации("ОтправкаПочты", УровеньЖурналаРегистрации.Ошибка, , , 
            "Ошибка при отправке письма: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Шаг 4. Передача данных между процедурами

Часто возникает вопрос: как правильно передать результат поиска во вторую процедуру для отправки? Рассмотрим два основных способа:

  1. Функция с возвратом Таблицы Значений: Первая функция выполняет запрос и возвращает ТаблицаЗначений. Вторая процедура принимает эту таблицу в качестве параметра. Это удобно, если логика разделена.
  2. Менеджер временных таблиц (МВТ): Если вы работаете в рамках одного серверного вызова, можно поместить результаты запроса во временную таблицу и передать МенеджерВременныхТаблиц. Это самый профессиональный и производительный метод для больших объемов данных.

Разберем пример с передачей ТаблицыЗначений:


&НаСервере
Процедура ВыполнитьОбработкуОчереди()
    
    ДанныеДляОтправки = ПолучитьНовыеЗаписиИзРегистра();
    
    Если ДанныеДляОтправки.Количество() > 0 Тогда
        ТекстСообщения = СформироватьТекстИзТаблицы(ДанныеДляОтправки);
        ОтправитьУведомление("support@company.ru", "Зависшие чеки ККМ", ТекстСообщения);
        ПометитьЗаписиКакОтправленные(ДанныеДляОтправки);
    КонецЕсли;
    
КонецПроцедуры

Важные рекомендации для промышленной эксплуатации

Чтобы ваше решение было отказоустойчивым, проанализируем следующие моменты:

Безопасность: Никогда не храните пароли от почты прямо в коде в открытом виде. Используйте Безопасное хранилище данных или константы с ограниченным доступом. Для регламентных заданий часто требуется УстановитьПривилегированныйРежим(Истина), чтобы гарантировать доступ к контактной информации пользователей или системным настройкам почты.

Логирование: Обязательно используйте конструкцию Попытка...Исключение при работе с объектом ИнтернетПочта. Ошибки сети, изменения паролей или сбои SMTP-сервера не должны приводить к аварийному завершению работы регламентного задания. Все ошибки фиксируйте в ЖурналРегистрации.

Лимиты: Помните об ограничениях почтовых сервисов на количество писем в час/день. Если записей очень много, лучше формировать одно сводное письмо (как мы сделали в примере с циклом), чем отправлять отдельное письмо по каждой строке регистра.

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

← На главную