Работа с электронной почтой в 1С через протокол IMAP является стандартной задачей, однако разработчики часто сталкиваются с ситуацией, когда фильтрация писем (например, по адресу отправителя) работает нестабильно: на одних ящиках письма находятся, на других — нет. В этой статье мы подробно разберем причины такого поведения и рассмотрим проверенные способы настройки надежного получения заголовков писем.
Для начала рассмотрим стандартный код, который обычно используется для подключения к почтовому серверу и получения заголовков с фильтром. В 1С для этого используется объект ИнтернетПочта и метод ПолучитьЗаголовки. Проанализируем типичный пример реализации:
Профиль = Новый ИнтернетПочтовыйПрофиль;
Профиль.ИспользоватьSSLIMAP = Истина;
Профиль.АдресСервераIMAP = "imap.yandex.ru";
Профиль.ПортIMAP = 993;
Профиль.ПарольIMAP = "Ваш_Пароль_Приложения";
Профиль.ПользовательIMAP = "login@yandex.ru";
Почта = Новый ИнтернетПочта;
Почта.Подключиться(Профиль, ПротоколИнтернетПочты.IMAP);
ОтборЗаголовков = Новый Структура;
ОтборЗаголовков.Вставить("Отправитель", "sender@domain.ru");
// Попытка получить заголовки по фильтру
Заголовки = Почта.ПолучитьЗаголовки(ОтборЗаголовков);
Несмотря на корректность кода, на практике фильтрация может "срабатывать через раз". Выясним причины этого явления по шагам.
Одной из самых распространенных причин отсутствия писем в выборке является структура почтового ящика на сервере. По умолчанию метод ПолучитьЗаголовки обращается только к корневой папке (обычно это INBOX). Если на почтовом сервере настроены правила перемещения писем в другие папки, 1С их просто не увидит.
Разберем, как правильно указать путь к нужной папке. Для этого используется свойство ТекущийПочтовыйЯщик объекта ИнтернетПочта. Посмотрим на примере:
// Перед получением заголовков указываем нужную папку
Почта.ТекущийПочтовыйЯщик = "INBOX/Processed";
// Для некоторых серверов путь может быть просто "ИмяПапки"
Заголовки = Почта.ПолучитьЗаголовки(ОтборЗаголовков);
Важный нюанс: Имена папок на сервере могут зависеть от локализации. Хотя современные версии 1С стараются обрабатывать это автоматически, иногда требуется передавать имя папки именно так, как оно определено в протоколе (например, INBOX вместо "Входящие").
Следующая серьезная преграда — это кодировка поисковых запросов. Когда мы передаем структуру ОтборЗаголовков, 1С транслирует это в команду протокола IMAP SEARCH. Согласно стандартам, строковые значения критериев отбора отправляются в кодировке US-ASCII, если они содержат только латинские символы.
Проанализируем ситуацию с кириллицей:
почта@домен.рф), 1С пытается отправить запрос в кодировке UTF-8.UTF8=ACCEPT в своих возможностях (CAPABILITY), поисковый запрос может вернуть пустой результат или ошибку.В такой ситуации рекомендуется использовать только латинские написания адресов, если это возможно, либо переходить к стратегии клиентской фильтрации, которую мы рассмотрим ниже.
Разберем, как сервер интерпретирует поле "Отправитель". Разные почтовые сервисы (Yandex, Gmail, Mail.ru, Exchange) могут по-разному обрабатывать поиск по этому полю. Одни ищут строгое соответствие в поле SENDER, другие — вхождение подстроки в поле From, которое может содержать и имя пользователя, например: Иван Иванов <ivan@mail.ru>.
Если вы передаете в фильтр строку "ivan@mail.ru", а сервер ожидает точного совпадения с заголовком, содержащим имя, поиск может провалиться. Попробуйте разные варианты написания в структуре отбора:
ivan@mail.ru<ivan@mail.ru>Если серверный фильтр работает нестабильно из-за специфики протокола SEARCH, самым надежным решением в среде 1С будет комбинированный подход. Мы минимизируем выборку на стороне сервера по самому простому критерию (например, по дате), а окончательную проверку отправителя делаем уже в коде 1С.
Проанализируем пример такого подхода:
Отбор = Новый Структура;
// Ограничим выборку только датой, чтобы не тянуть лишнее
// Метод Дата() здесь для примера, используйте нужную вам дату
Отбор.Вставить("ДатаОтправления", НачалоДня(ТекущаяДата()));
Заголовки = Почта.ПолучитьЗаголовки(Отбор);
Для Каждого Заголовок Из Заголовки Цикл
// Проверяем адрес отправителя уже внутри 1С
// Это исключает проблемы с кодировками IMAP SEARCH
Если Найти(НРег(Заголовок.Отправитель.Адрес), "sender@domain.ru") > 0 Тогда
// Загружаем письмо целиком, если заголовка недостаточно
МассивЗаголовков = Новый Массив;
МассивЗаголовков.Добавить(Заголовок);
Письма = Почта.Выбрать(Ложь, МассивЗаголовков);
// Обработка письма...
КонецЕсли;
КонецЦикла;
Этот метод гарантирует 100% результат, так как фильтрация происходит средствами встроенного языка 1С над уже полученными данными заголовка, и мы не зависим от того, как сервер интерпретирует команды поиска.
При работе с высоконагруженными почтовыми ящиками следует учитывать еще несколько факторов:
ДатаОтправления), чтобы поисковый индекс сервера работал быстрее.ОтборЗаголовков по условию И. Если вы укажете одновременно неверную дату и отправителя, вы не получите ничего.ИнтернетПочта категорически не справляется с вашим сервером (например, специфический Microsoft Exchange), рассмотрите использование внешних библиотек через COM-соединение или .NET (например, MailKit). Это даст более низкоуровневый контроль над сессией IMAP.Подводя итог, можно сказать: для создания максимально отказоустойчивой системы получения почты в 1С, лучше всего комбинировать фильтр по дате на стороне сервера с детальным анализом свойств ИнтернетПочтовоеСообщение на стороне клиента.