Почему 1С 7.7 не видит вложения XLS или вылетает при получении почты через ROM-Mail и DialMail?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При организации автоматического обмена электронными письмами в 1С:Предприятие 7.7 разработчики часто сталкиваются с ситуацией, когда обработка успешно считывает заголовки и тело сообщения, но не находит вложенные файлы (например, прайс-листы или заявки в формате XLS), либо процесс 1cv7s.exe аварийно завершает работу при попытке обработки конкретного входящего письма.

Разберем подробнее, почему возникают подобные сбои при использовании популярных внешних компонент ROM-Mail.dll и DialMail.dll, а также рассмотрим надежные способы решения этой проблемы.

Причины сбоев при разборе почтовых вложений в 1С 7.7

Проанализируем технические факторы, из-за которых старые внешние компоненты перестают корректно считывать файлы:

  1. Несовместимость с кодировкой UTF-8 и стандартом RFC 2231: Современные почтовые серверы и почтовые клиенты (Яндекс, Mail.ru, Gmail, Outlook) кодируют кириллические имена файлов по стандартам RFC 2231/RFC 2047 в UTF-8. Компонента ROM-Mail разрабатывалась для работы с кодировками Windows-1251 и KOI8-R. При попытке разобрать длинную неразрывную строку заголовка или специфический формат имени файла происходит переполнение буфера памяти (Access Violation), что приводит к моментальному вылету платформы 1С 7.7 без вывода ошибок.
  2. Сложная структура MIME-сообщения: Если письмо отправлено в формате HTML с оформлением или встроенными изображениями, файл может находиться в контейнерах multipart/related или multipart/alternative, а параметр Content-Disposition иметь значение inline вместо attachment. Компонента DialMail в стандартном режиме сканирует только корневые вложения, поэтому функция возвращает нулевое количество файлов.
  3. Блокировка типов файлов на уровне почтового сервера: Корпоративные почтовые шлюзы могут изменять MIME-тип вложения XLS на application/octet-stream либо упаковывать подозрительные файлы в защитные контейнеры, если в них содержатся макросы.

Типовой код загрузки почты через ROM-Mail

Посмотрим на классический пример загрузки почты в 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 По ВК.КоличествоФайлов() Цикл
            ИмяФайла = ВК.ПолучитьФайл(Инд);
            Сообщить("Успешно сохранен файл: " + ИмяФайла);
        КонецЦикла;
    КонецЕсли;
КонецЦикла;

ВК.Отключиться();

Если на шаге вызова метода ПолучитьСообщение() или ПолучитьФайл() происходит падение программы, это свидетельствует о невозможности компоненты разобрать сырой текст заголовков конкретного письма.

Вариант 1: Использование системного объекта CDO.Message без сторонних DLL

Разберем наиболее надежный способ чтения современной почты в среде 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: " + ИмяФайла);
    КонецЦикла;
КонецЕсли;

Вариант 2: Архитектурное разделение (внешний скрипт загрузки)

Поскольку встроенные возможности платформы 7.7 ограничены 32-битными библиотеками, стабильным решением в промышленной эксплуатации является перенос функции забора почты на внешний скрипт:

  1. Внешний сборщик: Создаем отдельный скрипт (на Python, PowerShell или VBScript) либо настраиваем стандартный почтовый клиент (например, Thunderbird или Outlook), который подключается к ящику по протоколам POP3/IMAP (включая защищенные порты с SSL/TLS), скачивает файлы XLS и складывает их в выделенный каталог обмена на сервере.
  2. Обработка в 1С 7.7: В конфигурации 1С по расписанию или по кнопке запускается поиск файлов в указанном каталоге с помощью стандартных средств:
    
    КаталогОбмена = "C:\MailExchange\";
    ИмяФайла = ФС.НайтиПервыйФайл(КаталогОбмена + "*.xls");
    
    Пока ПустаяСтрока(ИмяФайла) = 0 Цикл
        Если (ИмяФайла <> ".") И (ИмяФайла <> "..") Тогда
            Сообщить("Обработка файла заявки: " + ИмяФайла);
            // Выполняем загрузку данных в документ
        КонецЕсли;
        ИмяФайла = ФС.НайтиСледующийФайл();
    КонецЦикла;
    

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

← На главную