При автоматизации работы с электронной почтой в среде 1С:Предприятие разработчики часто сталкиваются с задачей разбора входящей корреспонденции: необходимо найти письмо по критериям и переместить его в архивную или служебную папку. Однако стандартный метод ПереместитьВПочтовыйЯщик объекта ИнтернетПочта нередко ведет себя неожиданно — вместо перемещения создается копия письма, а исходное сообщение остается на месте. Попытки вызвать методы УдалитьСообщения и ОчиститьУдаленныеСообщения также могут не давать результата.
Разберем детально механику работы протокола IMAP в платформе 1С, выясним причины такого поведения и рассмотрим корректные программные решения.
Проанализируем технические особенности протокола IMAP и реализации объекта ИнтернетПочта, которые приводят к дублированию писем:
ОчиститьУдаленныеСообщения() объекта ИнтернетПочта не принимает параметров. Если передать в него массив идентификаторов сообщений, платформа может вызвать исключение либо не выполнить команду сжатия почтового ящика (команду EXPUNGE протокола IMAP).ТекущийПочтовыйЯщик). После выполнения метода ПереместитьВПочтовыйЯщик активный контекст может переключиться на папку назначения. В результате последующие команды удаления выполняются не в исходной папке, а в целевой, либо полностью игнорируются сервером.\Deleted на исходное письмо и последующая очистка папки (EXPUNGE). Если почтовый сервер не поддерживает специализированные расширения или требует отдельного подтверждения удаления, исходное письмо просто остается помеченным как удаленное.LOGOUT, то есть при вызове метода Отключиться().Рассмотрим по шагам, как исправить логику перемещения с использованием штатного метода платформы. Для этого необходимо контролировать активный почтовый ящик, пометить исходное письмо на удаление и вызвать метод очистки без параметров.
// Подключаемся к почтовому серверу
Почта = РаботаСПочтовымиСообщениямиСлужебный.ПодключениеКПочте(УчетнаяЗапись, Истина);
мПисьма = Новый Массив();
мПисьма.Добавить("imap-SU5CT1g=66301");
// 1. Выполняем перемещение в целевую папку
Почта.ПереместитьВПочтовыйЯщик(мПисьма, "INBOX/Проверка");
// 2. Явно возвращаем контекст в исходный ящик, откуда забирали письмо
Почта.ТекущийПочтовыйЯщик = "INBOX";
// 3. Помечаем исходное сообщение флагом на удаление
Почта.УдалитьСообщения(мПисьма);
// 4. Физически удаляем помеченные сообщения (метод вызывается БЕЗ параметров)
Почта.ОчиститьУдаленныеСообщения();
// 5. Завершаем сеанс для фиксации изменений на сервере
Почта.Отключиться();
Обратите внимание: вызов ОчиститьУдаленныеСообщения() обязательно должен выполняться без аргументов. Это инициирует отправку серверу команды окончательного стирания всех сообщений с установленным флагом удаления в текущей открытой папке.
Если используемый почтовый сервер имеет нестандартную реализацию команд или метод ПереместитьВПочтовыйЯщик вызывает ошибки, применим проверенный алгоритм ручного переноса. Посмотрим на пример реализации:
Почта = РаботаСПочтовымиСообщениямиСлужебный.ПодключениеКПочте(УчетнаяЗапись, Истина);
// 1. Устанавливаем исходную папку и получаем объект письма
Почта.ТекущийПочтовыйЯщик = "INBOX";
мПисьма = Новый Массив();
мПисьма.Добавить("imap-SU5CT1g=66301");
НайденныеПисьма = Почта.Выбрать(Ложь, мПисьма);
Если НайденныеПисьма.Количество() > 0 Тогда
Письмо = НайденныеПисьма[0];
// 2. Переключаемся в целевую папку и сохраняем туда копию сообщения
Почта.ТекущийПочтовыйЯщик = "INBOX/Проверка";
Почта.Послать(Письмо, ОбработкаТекстаИнтернетПочтовогоСообщения.НеОбрабатывать, ПротоколИнтернетПочты.IMAP);
// 3. Возвращаемся в исходную папку и удаляем исходное письмо
Почта.ТекущийПочтовыйЯщик = "INBOX";
Почта.УдалитьСообщения(мПисьма);
Почта.ОчиститьУдаленныеСообщения();
КонецЕсли;
Почта.Отключиться();
Такой подход обеспечивает полный контроль над процессом: копия создается в нужной папке, после чего исходный объект гарантированно удаляется из входящих сообщений.