Вдохнем вторую жизнь во встроенный почтовый клиент из 1С:Управление торговлей 10.3



Хотели было воспользоваться почтовым клиентом из Управление торговлей 10.3, да не тут-то было. К сожалению, фирма «1С» почти совсем ее забросила и если Ваш респондент отправляет Вам письма, содержащие HTML, то Вас ждут матюки… Ну что же, как говорится: «Спасение утопающих — дело рук самих утопающих».

Недавно возникла необходимость воспользоваться почтовым клиентом в Управление торговлей 10.3. Собирались получать письма из почтового ящика на Яндексе. Новый почтовый ящик — на нем лежало-то всего-ничего — пара писем от Яндекса с благодарностью за регистрацию. И каково же было удивление когда выяснилось, что даже эти несчастные письма мы получить не можем. Если письма содержали HTML то попытка получения этих писем приводила к ошибке:

{ОбщийМодуль.УправлениеЭлектроннойПочтой.Модуль(205)}: Метод объекта не обнаружен (tags)
        ТегиКартинок = НовыйHTMLДокумент.all.tags("img");
 

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

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

//НовыйHTMLДокумент = Новый COMОбъект("HtmlFile");
//НовыйHTMLДокумент.open("text/html");
//НовыйHTMLДокумент.write(ХТМЛ_Текст);
//НовыйHTMLДокумент.close();
//ТегиКартинок = НовыйHTMLДокумент.all.tags("img");
//Для а = 0 По ТегиКартинок.length - 1 Цикл
// ИсточникКартинки = ТегиКартинок.item(а).src;
// Если Найти(ИсточникКартинки, "cid:") = 1 Тогда
//  ИсточникКартинки = Сред(ИсточникКартинки, 5);
//  ТегиКартинок.item(а).src = ИсточникКартинки;
// КонецЕсли;
//КонецЦикла;
//ПисьмоОбъект.ТекстПисьма = НовыйHTMLДокумент.all.tags("html").item(0).outerHTML;
ПисьмоОбъект.ТекстПисьма = ХТМЛ_Текст;

На этом дело не закончилось. При попытке просмотра некоторых писем вываливалось аналогичное сообщение об ошибке:

{ОбщийМодуль.УправлениеЭлектроннойПочтой.Модуль(3095)}: Поле объекта не обнаружено (innerText)
    Возврат СтрЗаменить(НовыйHTMLДокумент.all.item(0).innerText, Символ(13), "");
 

Тут на помощь нам приходит более современная конфигурация УНФ, разработчикам которой есть дело до того как в ней работает встроенный почтовый клиент. Все в том же модуле "УправлениеЭлектроннойПочтой" в процедуре "ПреобразоватьТекстИзХТМЛФорматаВПростой" закомментировал кусок кода и вставил под ним строки для обхода:

//НовыйHTMLДокумент = Новый COMОбъект("HtmlFile");
//НовыйHTMLДокумент.open("text/html");
//НовыйHTMLДокумент.write(ТекстВФорматеХТМЛ);
//НовыйHTMLДокумент.close();

//Возврат СтрЗаменить(НовыйHTMLДокумент.all.item(0).innerText, Символ(13), "");

ПереводСтроки = Символы.ВК + Символы.ПС;

ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "</o:p>", "</o:p>" + ПереводСтроки);
ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "</o:p>" + ПереводСтроки + ПереводСтроки, "</o:p>" + ПереводСтроки);
ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "</p>", "</p>" + ПереводСтроки);
ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "</p>" + ПереводСтроки + ПереводСтроки, "</p>" + ПереводСтроки);
ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "</div>", "</div>" + ПереводСтроки);
ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "</div>" + ПереводСтроки + ПереводСтроки, "</div>" + ПереводСтроки);
ТекстВФорматеХТМЛ = СтрЗаменить(ТекстВФорматеХТМЛ, "<br>", ПереводСтроки + ПереводСтроки);

Построитель = Новый ПостроительDOM;
ЧтениеHTML = Новый ЧтениеHTML;
ЧтениеHTML.УстановитьСтроку(ТекстВФорматеХТМЛ);

ДокументHTML = Построитель.Прочитать(ЧтениеHTML);

УдалитьТегиИзЭлементаHTML(ДокументHTML, "style");

Если ДокументHTML.Тело = Неопределено Тогда
Возврат "";
КонецЕсли;

Возврат ДокументHTML.Тело.ТекстовоеСодержимое;

И добавить процедуру:

Процедура УдалитьТегиИзЭлементаHTML(ЭлементHTML, Тег)

Для каждого Узел Из ЭлементHTML.ДочерниеУзлы Цикл
Если НРег(Узел.ИмяУзла) = НРег(Тег) Тогда
ЭлементHTML.УдалитьДочерний(Узел);
Иначе
// Рекурсия
УдалитьТегиИзЭлементаHTML(Узел, Тег);
КонецЕсли;
КонецЦикла;

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

Я же вообще вставил туда вызов функции "ПолучитьТекстИзHTML" из модуля "Гипертекст" из последних релизов УНФ. Подумалось что может еще что-нибудь оттуда пригодится. Правда придется немного обработать его "напильником" (дело в том что там активно используются новые функции "СтрШаблон" и "Найти").

Так как организация, для которой это делалось, активно использовала механизм событий (собственно из-за чего и начался весь сырбор с интеграцией почты в 1С) то само собой возник вопрос почему документ "Электронное письмо" не тождественен событию. Так например в той же УНФ разрабы реализовали электронное письмо как один из вариантов события (т.е. у них нет в принципе такой отдельной от события сущности как "Электронное письмо").

Вообщем в итоге решили генерировать документы "Событие" при отправке и получении электронных писем. Для создания документа "Событие" при отправки электронного письма все в том же модуле "УправлениеЭлектроннойПочтой" в процедуре "ПолучениеОтправкаПисем" добавил кусок кода:

НовоеСобытие = Документы.Событие.СоздатьДокумент();
Если (Письма <> Неопределено) И (Письма.Получить(Письмо) <> Неопределено) Тогда
НовоеСобытие.Заполнить(Письма[Письмо].Ссылка);
Иначе
НовоеСобытие.Заполнить(Письмо.Ссылка);
КонецЕсли;
НовоеСобытие.Дата    = ТекущаяДата();
НовоеСобытие.ТипСобытия   = Перечисления.ВходящееИсходящееСобытие.Исходящее;
НовоеСобытие.СостояниеСобытия = Перечисления.СостоянияСобытий.Завершено;
НовоеСобытие.Записать(РежимЗаписиДокумента.Проведение);

Вставить его нужно сразу после кода отправки:

 

Аналогично для создания документа "Событие" при получении электронного письма все в том же модуле "УправлениеЭлектроннойПочтой" в той же процедуре "ПолучениеОтправкаПисем" добавил кусок кода:

НовоеСобытие = Документы.Событие.СоздатьДокумент();
НовоеСобытие.Заполнить(Письмо.Ссылка);
НовоеСобытие.Дата    = Письмо.ДатаОтправления;
НовоеСобытие.ТипСобытия   = Перечисления.ВходящееИсходящееСобытие.Входящее;
НовоеСобытие.СостояниеСобытия = Перечисления.СостоянияСобытий.Завершено;
НовоеСобытие.Записать(РежимЗаписиДокумента.Проведение);

Вставить его нужно сразу после кода получения:

 

Сразу хочу заметить что поле "СодержаниеСобытия" не заполнялось нами по просьбе заказчика. Предполагается что там не будет содержаться текст электронного письма, а будут вноситься пометки менеджерами характеризующие кратко суть написанного.

Если же Вы решите не идти путем автоматического дублирования событий на основе электронных писем, но все же вводить события на основании будете интерактивно Вы наткнетесь на те же грабли:

{Документ.Событие.МодульОбъекта(416)}: Поле объекта не обнаружено (innerText)
        НовоеСобытие.Заполнить(ЭлементыФормы.ЭлектронныеПисьмаСписок.ТекущиеДанные.Ссылка);
 

Соответственно идем в модуль объекта документа "Событие" в процедуру "ОбработкаЗаполнения", комментируем кусок кода и вставляем под ним строку для обхода (при условии конечно что Вы вносили в него правки, которые я приводил во втором фрагменте кода):

//НовыйHTMLДокумент = Новый COMОбъект("HtmlFile");
//НовыйHTMLДокумент.open("text/html");
//НовыйHTMLДокумент.write(ДокОснование.ТекстПисьма);
//НовыйHTMLДокумент.close();
//СодержаниеСобытия = СтрЗаменить(НовыйHTMLДокумент.all.item(0).innerText, Символ(13), "");
СодержаниеСобытия = УправлениеЭлектроннойПочтой.ПреобразоватьТекстИзХТМЛФорматаВПростой(ДокОснование.ТекстПисьма);

Итак, друзья мои, кто осилил дочитать до этого места не буду Вас больше утомлять кодом настало время картинок 🙂

Решили что гораздо красивее внешний вид формы обработки "Менеджер контактов" (именно она отображает почту) будет выглядеть (мониторы то нонче у всех широкие):

Вместо типового вида (который как в ширину не тяни — все равно ни списка писем толком не видно, да и само письмо отображается куцо):

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

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

P.S. Все вышесказанное справедливо (тестировалось) на Управление торговлей 10.3.35.1 и 10.3.40.1 но думаю что будет работать плюс минус десяток версий т.к. туда давненько никто из 1С не лазил.

8 Comments

  1. lunjio

    Ну уж если вдыхаете вторую жизнь, давайте сделаем и возможность получения писем с любых почтовых серверов, по любым протоколам. У меня есть внешняя база на 8.3, которая работает как прослойка, она принимает данные с УТ 10.3, в виде — данные для авторизации, дата начала получения писем, возвращает на клиент идентификаторы писем, там стандартной процедурой по уже полученным письмам отсекаются полученные, затем по оставшимся не имеющимся идентификаторам идет получение писем. В этой конфигурации — проводнике, получение идет по протоколу IMAP, засчет чего работают фильтры, при этом при наличии большого количества писем в ящике, проблема деградации по времени получения отпадает. На днях выложу конфигурацию, если кому интересно, обмен правда происходит через веб-сервисы.

    Reply
  2. 1c-intelligence
    Вдохнем вторую жизнь во …

    с этой фразы, наверное, начинается карьера некромантов 🙂

    Reply
  3. 1c.pro.fun

    (1) Безусловно было бы интересно посмотреть — выкладывайте. Думаю что работа по IMAP будет востребована тем у кого «старые» ящики. Мне было бы интересно посмотреть.

    Reply
  4. nyam-nyam

    (2)Да ладно, если 7.7 ещё живёт и по слухам 6 даже где-то… 1С стоит старые версии OpenSource в перевести, вдруг заживёт усилиями энтузиастов. И будут на форумах спрашивать какой форк УТ лучше поставить… 🙂

    Reply
  5. ice-net

    (4) Кто тогда будет покупать новые?

    Reply
  6. nyam-nyam

    (5)Те же кто покупает прочий коммерческий софт.

    Reply
  7. Rustig

    при получении писем база сильно разрастается — я в свое время сразу отказался от этой идеи — и теперь я использую ут 10.3 только для оперативной отправки счетов и заказов, для приемки писем не использую. поэтому проблем с тегами ни разу не испытывал. ставлю + за рассмотрение проблемы.

    Reply
  8. 1c.pro.fun

    (7) В случае этого клиента один из трендов создание на базе УТ 10.3 полноценной CRM системы. Основные признаки уже налицо — телефонные звонки принимаются прямо в базе и автоматически регистрируются в событиях… Потому переписка по электронной почте (по сути ведь тоже события) должна в базу падать… понятно что с переходом в такой режим работы база будет пухнуть 🙁 но тут боюсь ничего не поделаешь.

    Reply

Leave a Comment

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