Механизм "Отложенная отправка писем", при записи документа

Иногда требуется отправлять письма при записи документа. Чтобы избежать проблем с производительностью, сделал механизм «Отложенная отправка писем».

В механизме реализовано: 

  • выбор времени отправки.
  • возможность прикрепить во вложение печатную форму "Табличный документ".
  • проверка по ссылке отправляли или нет письмо по данному документу.
  • возможность оправлять письма и без привязки к документу.

1. Создаем регистр сведений

Объект — тип ДокументСсылка

Вложения — тип ХранилищеЗначения

ДатаКогдаОтправить, ДатаОтправки — тип Дата и время

Адрес,Тема,Текст,Расширение — тип Строка

2. Добавляем регламентное задание, которое будет периодически отправлять письма.

3. К регламентному заданию привязываем процедуру, которая проверяет появились письма к отправке и отправляет их.

 
Процедура ОтложеннаяОтправкаПисем() Экспорт

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПисьмаОтправленные.Адрес КАК Адрес,
| ПисьмаОтправленные.Тема КАК Тема,
| ПисьмаОтправленные.Текст КАК Текст,
| ПисьмаОтправленные.Вложения КАК Вложения,
| ЕСТЬNULL(ПисьмаОтправленные.Объект.Номер, ""file"") КАК Номер,
| ПисьмаОтправленные.Объект КАК Объект,
| ПисьмаОтправленные.ДатаКогдаОтправить КАК ДатаКогдаОтправить,
| ПисьмаОтправленные.Расширение КАК Расширение
|ИЗ
| РегистрСведений.ОтложеннаяОтправкаПисем КАК ПисьмаОтправленные
|ГДЕ
| ПисьмаОтправленные.ДатаКогдаОтправить <= &ТекущаяДата
| И ПисьмаОтправленные.ДатаОтправки = &ПустаяДата";

Запрос.УстановитьПараметр("ПустаяДата", Дата(1,1,1));
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());

РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Отказ = Ложь;
СоответствиеВложений = Новый Соответствие;
МассивТабДок = ВыборкаДетальныеЗаписи.Вложения.Получить();
Если МассивТабДок <> Неопределено Тогда
Для Каждого ТабДокумент Из МассивТабДок Цикл
ИмяФайла = ВыборкаДетальныеЗаписи.Номер+ "." + ВыборкаДетальныеЗаписи.Расширение;
ИмяВременногоФайла = КаталогВременныхФайлов() + ИмяФайла;
Попытка
Если ВРег(ВыборкаДетальныеЗаписи.Расширение) = "XLS" Тогда
ТабДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLS);
ИначеЕсли ВРег(ВыборкаДетальныеЗаписи.Расширение) = "PDF" Тогда
ТабДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.PDF);
ИначеЕсли ВРег(ВыборкаДетальныеЗаписи.Расширение) = "XLSX" Тогда
ТабДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.XLSX);
ИначеЕсли ВРег(ВыборкаДетальныеЗаписи.Расширение) = "TXT" Тогда
ТабДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.TXT);
ИначеЕсли ВРег(ВыборкаДетальныеЗаписи.Расширение) = "ODS" Тогда
ТабДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.ODS);
ИначеЕсли ВРег(ВыборкаДетальныеЗаписи.Расширение) = "DOCX" Тогда
ТабДокумент.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.DOCX);
КонецЕсли;
Исключение
ОписаниеОшибки = ОписаниеОшибки();
Отказ = Истина;
Прервать;
КонецПопытки;
СоответствиеВложений.Вставить(ИмяФайла, Новый ДвоичныеДанные(ИмяВременногоФайла));
УдалитьФайлы(ИмяВременногоФайла);
КонецЦикла;
КонецЕсли;

Если Не Отказ Тогда
Попытка
Параметры1 = Новый Структура;
Параметры1.Вставить("Кому", ВыборкаДетальныеЗаписи.Адрес);
Параметры1.Вставить("Тема", ВыборкаДетальныеЗаписи.Тема);
Параметры1.Вставить("Тело", ВыборкаДетальныеЗаписи.Текст);
Параметры1.Вставить("ТипТекста", "Строка");
Параметры1.Вставить("Вложения", СоответствиеВложений);
//Тут идет отправка через типовой механизм БСП
РаботаСПочтовымиСообщениями.ОтправитьПочтовоеСообщение(Справочники.УчетныеЗаписиЭлектроннойПочты.СистемнаяУчетнаяЗаписьЭлектроннойПочты, Параметры1);
Исключение
ОписаниеОшибки = ОписаниеОшибки();
Отказ = Истина;
КонецПопытки;
КонецЕсли;

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

КонецПроцедуры

 

4. Добавляем в общий модуль процедуру регистрации новых писем к отправке.

 
Процедура ДобавитьПисьмоВРегистрПисьмаОтправленные(СтруктураНастройка) Экспорт

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

КонецПроцедуры

 

5. В модуль документа или другом месте добавляем вызов процедуры ДобавитьПисьмоВРегистрПисьмаОтправленные

 
&НаСервере
Процедура ОтправкаНаСервере()

объект1 = РеквизитФормыВЗначение("Объект");

ТабДокумент = Новый ТабличныйДокумент;
Макет    =  объект1.ПолучитьМакет("Макет");
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ТабДокумент.Вывести(ОбластьЗаголовок);

СтрНастройка = Новый Структура;
СтрНастройка.Вставить("Адрес", "abc123@abc123.ru");
СтрНастройка.Вставить("Тема" , "Тема письма");
СтрНастройка.Вставить("Текст", "Текст письма");
МассивТабДок = Новый Массив;
МассивТабДок.Добавить(ТабДокумент);
СтрНастройка.Вставить("МассивТабДок", МассивТабДок);
СтрНастройка.Вставить("Объект", Документ);
СтрНастройка.Вставить("Расширение", "XLS");
СтрНастройка.Вставить("ДатаКогдаОтправить", ТекущаяДата());
СлужебныеПроцедурыИФункции.ДобавитьПисьмоВРегистрПисьмаОтправленные(СтрНастройка);

КонецПроцедуры

 

6. Функция проверки отправляли письмо или нет по ссылке документа.

 
Функция ПисьмоОтправляли(Док) Экспорт

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПисьмаОтправленные.Объект КАК Объект
|ИЗ
| РегистрСведений.ОтложеннаяОтправкаПисем КАК ПисьмаОтправленные
|ГДЕ
| ПисьмаОтправленные.Объект = &Док";
Запрос.УстановитьПараметр("Док",Док);
Возврат Не Запрос.Выполнить().Пустой();

КонецФункции

 

Тестировал на платформе 1С:Предприятие 8.3 (8.3.13.1644)

6 Comments

  1. Поручик

    БСП: Получение и отправка электронных писем.

    УправлениеЭлектроннойПочтой.ПолучениеИОтправкаЭлектронныхПисем

    Reply ↓
  2. John_d

    (1) Спасибо, но одной процедуры без параметров недостаточно. Вот если бы ссылку на статью с подробным и простым описанием, как настроить это в БСП.

    Reply ↓
  3. Fragster

    (2) в БСП достаточно записать документ «ЭлектронноеПисьмоИсходящее» с заполненными реквизитами и он сам отправится в фоне. По заполнению реквизитов — в справку к БСП и списку процедур в ОтправкаПочтовыхСообщений и прочих у соответствующей подсистемы.

    Reply ↓
  4. volokitinac

    На большом объеме записей на регистре будет много

    база будет пухнуть из-за данных в МассивТабДок

    пару лет назад до БСП, пришлось писать аналог на двух очередях, подписках и регламентных заданиях

    1. Очередь для обработки новых документов для получения печатных форм

    2. Очередь для рассылки полученных документов

    как развитие можно завернуть на параллельные фоновые задания. но не стал.

    Reply ↓
  5. Трактор

    Я не гружу событие при записи. Регламентным заданием раз в минуту выбираю документы по которым надо отправить письма и создаю письма. Отправкой созданных писем занимается другое регламентное задание.

    Reply ↓
  6. John_d

    (5) Как вариант, но у меня требовали доказательств, что письма отправляются. Пользователи заходили в этот регистр и видели всю интересующую их информацию. С учетом, что тема и текст письма динамически формировались для разных получателей.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *