【问题标题】:Python IMAP: =?utf-8?Q? in subject stringPython IMAP: =?utf-8?Q?在主题字符串中
【发布时间】:2012-10-05 21:57:42
【问题描述】:

我正在显示带有IMAP 的新电子邮件,一切看起来都很好,除了一个邮件主题显示为:

=?utf-8?Q?Subject?=

我该如何解决?

【问题讨论】:

  • “我怎样才能修复它?” - 你为什么认为它坏了?
  • 它应该只显示“主题”——=?utf-8?Q 里面有什么? ... ?

标签: python email character-encoding imap mime


【解决方案1】:

在 MIME 术语中,这些编码块称为编码字。你可以像这样解码它们:

import email.header
text, encoding = email.header.decode_header('=?utf-8?Q?Subject?=')[0]

查看email.header 的文档了解更多详情。

【讨论】:

  • 在 Python 2 和 Python 3 中,email.header.decode_header(带有小写的m)是通用名称。此外,在您的代码中,text 实际上不是文本,而是字节变量。
【解决方案2】:

在 Python 3 中,将其解码为近似字符串非常简单:

from email.header import decode_header, make_header

decoded = str(make_header(decode_header("=?utf-8?Q?Subject?=")))

参见decode_headermake_header 的文档。

【讨论】:

    【解决方案3】:

    高级 IMAP 库可能在这里有用:imap_tools

    from imap_tools import MailBox, AND
    
    # get list of email subjects from INBOX folder
    with MailBox('imap.mail.com').login('test@mail.com', 'pwd', 'INBOX') as mailbox:
        subjects = [msg.subject for msg in mailbox.fetch()]
    
    • 已解析的电子邮件属性
    • 用于搜索电子邮件的查询生成器
    • 电子邮件操作:复制、删除、标记、移动、查看
    • 文件夹操作:列表、设置、获取、创建、存在、重命名、删除、状态
    • 无依赖关系

    【讨论】:

      【解决方案4】:

      在 Python 3.3+ 中,如果 policy 参数设置为 policy.defaultemail.parser 中的解析类和函数会自动解码标头中的“编码字”

      >>> import email
      >>> from email import policy
      
      >>> msg = email.message_from_file(open('message.txt'), policy=policy.default)
      >>> msg['from']
      'Pepé Le Pew <pepe@example.com>'
      

      解析类和函数有:

      令人困惑的是,至少在 Python 3.8 之前,这些解析函数的默认策略不是policy.default,而是policy.compat32,它解码“编码词”。

      >>> msg = email.message_from_file(open('message.txt'))
      >>> msg['from']
      '=?utf-8?q?Pep=C3=A9?= Le Pew <pepe@example.com>'
      

      【讨论】:

        【解决方案5】:

        试试Imbox

        因为imaplib 是一个非常低级的库,并且返回的结果很难处理

        安装

        pip install imbox

        用法

        from imbox import Imbox
        
        with Imbox('imap.gmail.com',
                username='username',
                password='password',
                ssl=True,
                ssl_context=None,
                starttls=False) as imbox:
        
            all_inbox_messages = imbox.messages()
            for uid, message in all_inbox_messages:
                message.subject
        

        【讨论】:

        • +1 确实这是给人类的。事实上,imbox 能够即时解码其他 base64 编码(在 imaplib 等中)主题和其他字段。但是,请注意,如果缺少某些字段,则会抛出 KeyError。
        【解决方案6】:

        这是一个 MIME encoded-word。可以用email.header解析:

        import email.header
        
        def decode_mime_words(s):
            return u''.join(
                word.decode(encoding or 'utf8') if isinstance(word, bytes) else word
                for word, encoding in email.header.decode_header(s))
        
        print(decode_mime_words(u'=?utf-8?Q?Subject=c3=a4?=X=?utf-8?Q?=c3=bc?='))
        

        【讨论】:

        • 你能用更 Pythonic 的方式重写它吗?
        • @wbg 这段代码有什么不是 Pythonic 的?你会改变什么?现在看,它对我来说似乎写得很好,是 Python 表现力的典范。也许generator expression 绊倒了@deterjan?如果您只是针对 Python 3,您可以跳过 ' 之前的 if isinstance(word, bytes) else wordu;此代码经过精心设计,可在 Python 2 和 3 上运行。
        猜你喜欢
        • 2018-04-30
        • 1970-01-01
        • 2012-10-18
        • 1970-01-01
        • 2022-11-12
        • 2012-10-17
        • 1970-01-01
        • 2015-06-02
        相关资源
        最近更新 更多