【问题标题】:Saving IMAP messages with Python mailbox module使用 Python 邮箱模块保存 IMAP 消息
【发布时间】:2015-06-08 14:10:11
【问题描述】:

我正在将带有 imaplib 的 IMAP 消息下载到 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

【问题讨论】:

    标签: python imap imaplib mbox


    【解决方案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 是一件非常痛苦的事情,因为您必须遍历所有消息。我想这将是非常糟糕。如果可能的话,最好将这些信息存储在其他地方。

    祝你好运!

    【讨论】:

    • 没错,获得最大的已保存 UID 是一项巨大的工作,因为必须进行迭代......那你会怎么做 @JosiahDaniels ?
    • 我不确定您有什么要求。例如,您可以将其存储在同一文件夹中的单独 json 文件中吗?还是将 UID 保存在 mmox 文件中很重要?
    • 我想要的只是不能将两次相同的消息重新下载到 mbox 中。我希望仅使用 mbox 而没有外部文件可以做到这一点。我正在寻找一个不错的 Pythonic 解决方案;)但是如果外部 JSON 是强制性的,那么我们就这样做吧……即使这很遗憾;)
    【解决方案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()
    

    Above 会将您的电子邮件转储到: D:\my_email\INBOX\msg_no_1.eml ... msg_no203.eml

    那么你需要这个秘密才能在 windows 上打开 eml:

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

    亲爱的 stockoverflow 审查员 - 请仁慈,我会发现上面有用;例如:smsg = msg.as_bytes().decode(encoding='ISO-8859-1') 花了很长时间才弄明白。

    【讨论】:

      猜你喜欢
      • 2011-01-05
      • 2011-01-04
      • 2018-02-05
      • 2013-02-08
      • 2014-08-26
      • 2013-03-01
      • 2019-05-24
      • 2019-03-01
      • 2020-09-27
      相关资源
      最近更新 更多