Как получить непрочитанные письма по протоколу IMAP в 1С: разбор ошибок и готовый код

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

Интеграция 1С с почтовыми сервисами — одна из классических задач автоматизации. Будь то загрузка заказов, обработка претензий или разбор уведомлений, разработчику часто требуется получать только новые (непрочитанные) сообщения. Например, при работе с заказами можно автоматизировать создание счетов и договоров в 1С на основании электронных писем. На первый взгляд задача кажется тривиальной, однако при её реализации программисты часто сталкиваются с зависаниями, медленной работой и непонятными ошибками авторизации.

В рамках этой статьи мы подробно разберем, почему стандартные механизмы могут работать медленно, исправим типичные ошибки подключения к популярным сервисам (таким как Яндекс.Почта) и напишем оптимизированный код для быстрого получения непрочитанных писем по протоколу IMAP.

В чем разница между POP3 и IMAP при работе с отборами в 1С

Рассмотрим ситуацию, с которой часто сталкиваются начинающие разработчики. При использовании устаревшего протокола POP3 попытка применить отбор по состоянию письма (прочитано/непрочитано) не приносит результата. Выясним причину этого поведения.

Протокол POP3 изначально проектировался как крайне простой механизм: он предназначен исключительно для скачивания писем с сервера на локальный компьютер. Этот протокол «не умеет» работать с флагами писем (такими как «Прочитано», «Помечено» или «Важное») прямо на сервере. Когда мы используем POP3 в 1С, платформа вынуждена скачивать заголовки абсолютно всех писем, хранящихся в ящике, и только потом пытаться фильтровать их на стороне клиента, что приводит к колоссальным временным затратам.

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

Шаг 1. Подготовка почтового ящика на примере Яндекс.Почты

Прежде чем приступать к написанию кода в 1С, необходимо правильно настроить сам почтовый ящик. Современные почтовые сервисы блокируют стандартный доступ по логину и паролю в целях безопасности. Без предварительной подготовки вы гарантированно получите ошибку авторизации вида LOGIN invalid credentials или authentication failed.

Выполним пошаговую настройку в веб-интерфейсе Яндекс.Почты:

  1. Перейдем в меню Все настройки -> Почтовые программы.
  2. Убедимся, что установлена галочка С сервера imap.yandex.ru по протоколу IMAP.
  3. Установим признак использования Паролей приложений и OAuth-токенов.
  4. Перейдем в личный кабинет Яндекс ID (раздел «Безопасность» -> «Пароли приложений»).
  5. Создадим новый пароль, выбрав тип приложения «Почта». Сервер сгенерирует уникальный 16-значный код (например, abcd-efgh-ijkl-mnop). Именно этот код, а не основной пароль от почты, мы будем указывать в коде 1С.

Шаг 2. Разбор ошибок инициализации подключения

Посмотрим на типичную ошибку при попытке подключиться по IMAP в 1С: Данная операция не может быть выполнена, так как адрес POP3 сервера не указан. Почему она возникает, если мы заполнили свойства АдресСервераIMAP и ПортIMAP?

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

Также важно не забывать про использование безопасного соединения. Современные почтовые серверы не принимают незашифрованные запросы, поэтому свойство ИспользоватьSSLIMAP обязательно должно быть установлено в значение Истина, а порт должен быть равен 993.

Шаг 3. Базовая реализация получения непрочитанных писем

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


&НаКлиенте
Процедура ПолучитьНепрочитанныеПисьма()

    // Настройка профиля подключения
    Профиль = Новый ИнтернетПочтовыйПрофиль;
    Профиль.АдресСервераIMAP = "imap.yandex.ru";
    Профиль.ПортIMAP = 993;
    Профиль.ПользовательIMAP = "my-email@yandex.ru"; // Обязательно полный адрес
    Профиль.ПарольIMAP = "abcd-efgh-ijkl-mnop";     // Пароль приложения
    Профиль.ИспользоватьSSLIMAP = Истина;

    Почта = Новый ИнтернетПочта;

    Попытка
        // Подключаемся, явно указывая протокол IMAP
        Почта.Подключиться(Профиль, ПротоколИнтернетПочты.IMAP);
        Сообщить("Успешно подключено к серверу IMAP!");
    Исключение
        Сообщить("Не удалось подключиться: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    // Задаем параметры отбора для получения только непрочитанных писем
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Seen", Ложь); // "Seen" со значением Ложь означает "Не прочитано"

    // Переходим в нужную папку (по умолчанию INBOX - Входящие)
    Почта.ТекущийПочтовыйЯщик = "INBOX";

    // Получаем заголовки писем по отбору
    Заголовки = Почта.ПолучитьЗаголовки(ПараметрыОтбора);

    Если Заголовки.Количество() > 0 Тогда
        // Загружаем сами сообщения на основе полученных заголовков
        МассивСообщений = Почта.Выбрать(Ложь, Заголовки, Истина);
        
        Для Каждого Письмо Из МассивСообщений Цикл
            Сообщить("Тема письма: " + Письмо.Тема + " | Отправитель: " + Письмо.Отправитель.Адрес);
        КонецЦикла;
    Иначе
        Сообщить("Нет новых непрочитанных писем.");
    КонецЕсли;

    Почта.Отключиться();

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

Шаг 4. Оптимизация скорости: ПолучитьИдентификаторы() вместо ПолучитьЗаголовки()

Рассмотренный выше вариант отлично работает на небольших ящиках. Но что делать, если в вашей корпоративной почте хранятся десятки тысяч писем? Метод ПолучитьЗаголовки(), даже с отбором, пытается прочитать метаданные (тему, дату, отправителя) всех писем, соответствующих условию. Это может нагружать оперативную память сервера 1С и снижать скорость обработки.

Для оптимизации процесса воспользуемся методом ПолучитьИдентификаторы(). Он возвращает массив уникальных идентификаторов (UID) писем, не скачивая их метаданные. UID — это простые текстовые строки, передача которых по сети происходит практически мгновенно. Получив список UID, мы можем порционно или целиком передать их в метод Выбрать().

Проанализируем также оптимизацию параметров самого метода Выбрать(). Третий параметр этого метода отвечает за то, нужно ли скачивать тело письма и вложения прямо сейчас. Если нам нужно сначала просто проанализировать заголовки или темы писем, мы передаем туда значение Ложь. Это в разы ускоряет работу алгоритма.

Посмотрим на пример оптимизированного кода с дополнительным ограничением выборки по дате (чтобы не сканировать древние непрочитанные письма):


&НаСервере
Процедура ПолучитьПисьмаОптимизированно()

    Профиль = Новый ИнтернетПочтовыйПрофиль;
    Профиль.АдресСервераIMAP = "imap.yandex.ru";
    Профиль.ПортIMAP = 993;
    Профиль.ПользовательIMAP = "my-email@yandex.ru";
    Профиль.ПарольIMAP = "abcd-efgh-ijkl-mnop";
    Профиль.ИспользоватьSSLIMAP = Истина;

    Почта = Новый ИнтернетПочта;

    Попытка
        Почта.Подключиться(Профиль, ПротоколИнтернетПочты.IMAP);
        Почта.ТекущийПочтовыйЯщик = "INBOX";
    Исключение
        ЗаписатьЛогСобытий("Ошибка подключения к почте: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    // Комбинированный отбор: только непрочитанные за последние 7 дней
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Seen", Ложь);
    
    // Ограничиваем глубину поиска для защиты от зависаний на больших ящиках
    ДатаНачалаПроверки = ТекущаяДата() - (24 * 60 * 60 * 7); // Минус 7 дней
    ПараметрыОтбора.Вставить("ПослеДатыОтправления", ДатаНачалаПроверки);

    // Быстро получаем легкие идентификаторы (UID) сообщений
    МассивИдентификаторов = Почта.ПолучитьИдентификаторы(ПараметрыОтбора);

    Если МассивИдентификаторов.Количество() > 0 Тогда
        
        // Скачиваем сообщения. 
        // Третий параметр = Ложь: скачиваем только заголовки, тела писем и вложения не загружаем.
        // Это экономит трафик и память.
        МассивСообщений = Почта.Выбрать(Ложь, МассивИдентификаторов, Ложь);
        
        Для Каждого Письмо Из МассивСообщений Цикл
            // Обрабатываем метаданные писем
            ТемаПисьма = Письмо.Тема;
            ДатаПисьма = Письмо.ДатаОтправления;
            
            // Если письмо удовлетворяет нашим условиям, мы можем загрузить его тело отдельно
            // или обработать информацию на месте
            Сообщить(СтрШаблон("Новое письмо от %1: %2 (%3)", Письмо.Отправитель.ОтображаемоеИмя, ТемаПисьма, ДатаПисьма));
        КонецЦикла;
        
    КонецЕсли;

    Почта.Отключиться();

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

Допустимые параметры отбора IMAP в 1С

Для построения гибких алгоритмов фильтрации важно знать, какие ключи поддерживает структура отбора при работе с объектом ИнтернетПочта по протоколу IMAP. Названия ключей регистронезависимы, но рекомендуется придерживаться стандартной терминологии Синтакс-Помощника:

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

← На главную