Сохранение сообщений IMAP с помощью модуля почтового ящика Python

Я загружаю сообщения из IMAP с imaplib в Mbox (с mailbox модуль):

import imaplib, mailbox
svr = imaplib.IMAP4_SSL('imap.gmail.com')
svr.login('myname@gmail.com', 'mypaswword')
resp, [countstr] = svr.select("[Gmail]/All Mail", True)

mbox = mailbox.mbox('mails.mbox')

for n in range(...):
  resp, lst1 = svr.fetch(n, 'UID')    # the UID of the message
  resp, lst2 = svr.fetch(n, '(RFC822)')   # the message itself
  mbox.add(lst2[0][1])      # add the downloaded message to the mbox
  #
  # how to store the UID of this current mail inside mbox? 
  #

Давайте загрузим почту с UID = 1 .. 1000, В следующий раз я хотел бы начать со 1001-го сообщения, а не с 1-го. Тем не мение, mailbox.mbox не хранит UID в любом месте. Поэтому в следующий раз, когда я открою файл mbox, будет невозможно узнать, где мы остановились.

Есть ли естественный способ с модулем mailbox хранить UID из писем?

Или, может быть, я не использую mailbox + imaplib так и должно быть?

2 ответа

Надеюсь это будет полезно

1) библиотеки и среда Win7 Anaconda3-4.3.1-Windows-x86_64.exe (доступно новое, но это то, что я использовал

2) Чтобы перечислить все ваши почтовые ящики:

import getpass, imaplib, sys

def main():
      hostname = 'my.mail.server'
      username = 'my_user_name'
      m = imaplib.IMAP4_SSL(hostname)
      m.login(username, 'passowrd')

   try:
      print('Capabilities:', m.capabilities)
      print('Listing mailboxes ')
      status, data = m.list()
      print('Status:', repr(status))
      print('Data:')
      for datum in data:
         print(repr(datum))

   finally:
      m.logout()

if __name__ == '__main__':
   main()

3) Используя сгенерированную выше информацию, мы можем выгрузить все почтовые сообщения с почтового сервера в каталоги:

import getpass, imaplib, sys, email, os , io
import codecs

BASE_NAME = 'msg_no_'
BASE_DIR = 'D:/my_email/'

def writeTofile(mailDir, partOfName, msg ):

   ## no need of dos backslash -- newDir = BASE_DIR + mailDir.replace('/', '\\')

   newDir = BASE_DIR + mailDir

   if not os.path.exists(newDir):
       os.makedirs(newDir)

   os.chdir(newDir)

   # print('Dir:' + os.getcwd() )

   file_name = BASE_NAME + partOfName  + '.eml'

   # print('Write:' + file_name)

   fw = open(newDir + '/' + file_name,'w', encoding="utf-8")
   fw.write( msg )
   fw.close()

   return


def processMailDir(m, mailDir):

   print('MailDIR:' + mailDir)

   m.select(mailbox=mailDir, readonly=True)
   typ, data = m.search(None, 'ALL')

   for num in data[0].split():
      typ, data = m.fetch(num, '(RFC822)')
      msg = email.message_from_bytes(data[0][1])

      smsg = msg.as_bytes().decode(encoding='ISO-8859-1')

      writeTofile(mailDir, num.decode(), smsg )

   m.close()

   return


def main():

   if len(sys.argv) != 3:
      hostname = 'my.mail.server'
      username = 'my_username'
      m = imaplib.IMAP4_SSL(hostname)
      m.login(username, 'password')

   else:
      hostname, username = sys.argv[1:]
      m = imaplib.IMAP4_SSL(hostname)
      m.login(username, getpass.getpass())

   try:
      print('Start...')

      processMailDir(m, 'INBOX')
      processMailDir(m, 'Sent')
      processMailDir(m, 'archive/2013/201301')
      processMailDir(m, 'archive/2013/201302')
# etc.. etc.. simple as it can be but not simpler
      print('Done...')

   finally:
      m.logout()

if __name__ == '__main__':
   main()

Выше будут отправлять ваши электронные письма в: D:\my_email\INBOX\msg_no_1.eml ... msg_no203.eml

тогда вам нужен этот секрет, чтобы открыть eml's на окнах:

Administrator: cmd.com:

assoc .eml=Outlook.File.eml
ftype Outlook.File.eml="C:\Program Files (x86)\Microsoft Office\Office12\OUTLOOK.EXE" /eml "%1"

Уважаемый цензурный сток - будьте милостивы, я бы нашел это полезным; например, это: smsg = msg.as_bytes().decode(encoding='ISO-8859-1') потребовалось много времени, чтобы выяснить это.

Чтобы ответить на ваш вопрос: после долгого времени, глядя на документы, я не видел никакого чистого способа сделать то, что вы ищете. Если абсолютно необходимо, чтобы идентификаторы UID хранились в файле mbox, я бы предложил добавить настраиваемый заголовок UID к электронным письмам, которые вы храните:

message = email.message_from_string(lst2[0][1])
message.add_header("my_internal_uid_header", lst1[0][1])
mbox.add(message)

Теперь, конечно, ОГРОМНАЯ боль - получить самый большой сохраненный UID, потому что вам приходится перебирать все сообщения. Я представляю, что это было бы действительно плохо. Если это вообще возможно, было бы лучше хранить такую ​​информацию в другом месте.

Удачи!

Другие вопросы по тегам