При организации автоматического обмена электронными письмами в 1С:Предприятие 7.7 разработчики часто сталкиваются с ситуацией, когда обработка успешно считывает заголовки и тело сообщения, но не находит вложенные файлы (например, прайс-листы или заявки в формате XLS), либо процесс 1cv7s.exe аварийно завершает работу при попытке обработки конкретного входящего письма.
Разберем подробнее, почему возникают подобные сбои при использовании популярных внешних компонент ROM-Mail.dll и DialMail.dll, а также рассмотрим надежные способы решения этой проблемы.
Проанализируем технические факторы, из-за которых старые внешние компоненты перестают корректно считывать файлы:
ROM-Mail разрабатывалась для работы с кодировками Windows-1251 и KOI8-R. При попытке разобрать длинную неразрывную строку заголовка или специфический формат имени файла происходит переполнение буфера памяти (Access Violation), что приводит к моментальному вылету платформы 1С 7.7 без вывода ошибок.multipart/related или multipart/alternative, а параметр Content-Disposition иметь значение inline вместо attachment. Компонента DialMail в стандартном режиме сканирует только корневые вложения, поэтому функция возвращает нулевое количество файлов.XLS на application/octet-stream либо упаковывать подозрительные файлы в защитные контейнеры, если в них содержатся макросы.Посмотрим на классический пример загрузки почты в 1С 7.7 с использованием внешней компоненты ROM-Mail.dll:
Попытка
Если ЗагрузитьВнешнююКомпоненту("ROM-Mail.dll") = 0 Тогда
Сообщить("Не удалось загрузить ROM-Mail.dll");
СтатусВозврата(0);
Возврат;
КонецЕсли;
Исключение
Сообщить("Ошибка при загрузке библиотеки ROM-Mail.dll");
СтатусВозврата(0);
Возврат;
КонецПопытки;
ВК = СоздатьОбъект("AddIn.AddInMail");
ВК.СерверПриема = СокрЛП(ВыбСервер);
ВК.ПортПриема = СокрЛП(ВыбПорт);
ВК.Логин = СокрЛП(ВыбЛогин);
ВК.Пароль = СокрЛП(ВыбПароль);
ВК.ОставлятьНаСервере = 1;
ВК.ПоказыватьПредупреждения = 0;
ВК.СохранятьСоединение = 1;
ВК.КаталогВложений = КаталогПользователя();
Если ВК.Подключиться("Прием") = 0 Тогда
Предупреждение("Не удалось подключиться к серверу!");
Возврат;
КонецЕсли;
Для Индекс = 1 По ВК.КоличествоСообщений() Цикл
Если ВК.ПолучитьСообщение(Индекс) = 0 Тогда
Продолжить;
КонецЕсли;
Если (Дата1 <= Дата(ВК.ДатаОтправки)) И (Дата(ВК.ДатаОтправки) <= Дата2) Тогда
Если ВК.КоличествоФайлов() = 0 Тогда
Сообщить("В письме '" + ВК.Тема + "' не обнаружены вложения.");
Продолжить;
КонецЕсли;
Для Инд = 1 По ВК.КоличествоФайлов() Цикл
ИмяФайла = ВК.ПолучитьФайл(Инд);
Сообщить("Успешно сохранен файл: " + ИмяФайла);
КонецЦикла;
КонецЕсли;
КонецЦикла;
ВК.Отключиться();
Если на шаге вызова метода ПолучитьСообщение() или ПолучитьФайл() происходит падение программы, это свидетельствует о невозможности компоненты разобрать сырой текст заголовков конкретного письма.
Разберем наиболее надежный способ чтения современной почты в среде Windows для 1С 7.7 — использование стандартного системного COM-объекта CDO.Message. Он корректно обрабатывает кириллицу в UTF-8, multipart-структуры и любые типы вложений без риска падения платформы:
Письмо = СоздатьОбъект("CDO.Message");
Конфигурация = СоздатьОбъект("CDO.Configuration");
Конфигурация.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing").Value = 2;
Конфигурация.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value = СокрЛП(ВыбСервер);
Конфигурация.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport").Value = 25;
Конфигурация.Fields.Update();
Письмо.Configuration = Конфигурация;
// Для чтения локально сохраненного сырого EML-файла:
Письмо.DataSource.Open(КаталогПользователя() + "mail.eml");
КолвоВложений = Письмо.Attachments.Count;
Если КолвоВложений > 0 Тогда
Для Ном = 1 По КолвоВложений Цикл
Вложение = Письмо.Attachments.Item(Ном);
ИмяФайла = КаталогПользователя() + Вложение.FileName;
Вложение.SaveToFile(ИмяФайла);
Сообщить("Сохранен файл через CDO: " + ИмяФайла);
КонецЦикла;
КонецЕсли;
Поскольку встроенные возможности платформы 7.7 ограничены 32-битными библиотеками, стабильным решением в промышленной эксплуатации является перенос функции забора почты на внешний скрипт:
XLS и складывает их в выделенный каталог обмена на сервере.
КаталогОбмена = "C:\MailExchange\";
ИмяФайла = ФС.НайтиПервыйФайл(КаталогОбмена + "*.xls");
Пока ПустаяСтрока(ИмяФайла) = 0 Цикл
Если (ИмяФайла <> ".") И (ИмяФайла <> "..") Тогда
Сообщить("Обработка файла заявки: " + ИмяФайла);
// Выполняем загрузку данных в документ
КонецЕсли;
ИмяФайла = ФС.НайтиСледующийФайл();
КонецЦикла;
Такой подход полностью изолирует учетную систему от проблем с сетевыми таймаутами, кодировками почтовых заголовков и падениями из-за сбоев сторонних внешних компонент.