Python3, imaplib, команда удаления, используемая в соответствии с сообщением в цикле для всех сообщений в папке

#python #imap #imaplib

Вопрос:

У меня есть куча функций для хранения всех вложений из всех писем в одной папке imap. Вложения представляют собой наборы данных json для дальнейшей обработки. Чтобы избежать сбоев после потери соединения и повторного подключения, я вставлял команду удаления после каждого сообщения в цикле. Это приводит к спорадическим ошибкам при обработке сообщения электронной почты или, лучше сказать: я не могу прочитать текст письма, что приводит к [нет] для тела. Чтобы решить проблему, я поместил команду удаления после цикла и вставил другую команду удаления перед циклом, чтобы удалить помеченные сообщения, чтобы предотвратить многократную обработку.

Хотя моя функция работает безупречно, возможно, кто-нибудь может рассказать мне о поведении команды удаления на сервере ( не могу сказать, какой imap-сервер работает на стороне сервера, поставщик ionos.de). Я не могу найти соответствующую информацию в документе RFC. Может быть, какое-то состояние гонки.

Это код, который приводит к ошибкам:

 def downloadAllAttachmentsInInbox( **args):

conf =args['conf']

m = connectImapServer( conf.imappoll.server, conf.imappoll.account, conf.imappoll.password)
resp, items = m.search( None, "(ALL)")
items = items[0].split()
for emailid in items:
    downloaAttachmentsInEmail( m =m, emailid =emailid, conf =conf)
    # Markiere Mail zum löschen
    if conf.imappoll.clearmb =="True":
        m.store( emailid, ' FLAGS', '\Deleted')
        # Loesche markierte Mail(s)
        m.expunge()
# Schliesse Mailbox, logout aus Server
m.close()
m.logout()
 

И это рабочий код:

 def downloadAllAttachmentsInInbox( **args):

conf =args['conf']

m = connectImapServer( conf.imappoll.server, conf.imappoll.account, conf.imappoll.password)
# Loesche bereits zur Löschung markierte Mails vom Server vor Abruf aller Nachrichten
m.expunge()
resp, items = m.search( None, "(ALL)")
items = items[0].split()
for emailid in items:
    downloaAttachmentsInEmail( m =m, emailid =emailid, conf =conf)
    # Markiere Mail zum löschen
    if conf.imappoll.clearmb =="True":
        m.store( emailid, ' FLAGS', '\Deleted')
# Loesche markierte Mail(s)
m.expunge()
# Schliesse Mailbox, logout aus Server
m.close()
m.logout()
 

Ответ №1:

Если вы используете порядковые номера сообщений, вы не можете их использовать expunge , так как это изменяет нумерацию сообщений, что делает ваши результаты поиска устаревшими.

У вас есть пара вариантов:

  • Используйте UID везде. m.uid(‘SEARCH’, ‘ALL’) и m.uid(‘FETCH’, …) и m.uid(‘STORE’, …) . Идентификаторы UID не перенумеруются при удалении.
  • Не удаляйте, а вместо этого ищите НЕОТДЕЛЕННЫЕ, чтобы игнорировать сообщения, которые вы уже отметили удаленными (например, обработанными). m.search(‘UNDELETED’) . Затем выйдите за пределы цикла.