用python3处理电子邮件主题行中的国际字符

2024-06-28 11:38:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个脚本来阅读未读邮件的主题行。我的第一次尝试:

from imaplib import IMAP4_SSL
from email.parser import HeaderParser

# username = 
# password = 
# server = 
# port = 

M = IMAP4_SSL(server, port)
M.login(username, password)
M.select()
typ, data = M.search(None, '(UNSEEN)')

for num in data[0].split():
    rv, data = M.fetch(num, '(BODY.PEEK[HEADER.FIELDS (SUBJECT FROM)])')
    header_data = data[0][1].decode('utf-8')
    parser = HeaderParser()
    msg = parser.parsestr(header_data)
    subject = msg['Subject']
    print(subject)
    print()

这适用于大多数电子邮件,但当主题行中有非ascii字符时,它将失败。输出如下:

=?UTF-8?Q?This_email_has_internati=C3=B2nal_characters?=

所以看起来HeaderParser不处理编码(在RFC1342中指定)。看一下文档,我似乎需要使用decode_header和{}。我的第二次尝试:

^{pr2}$

输出如下:

This email has ASCII only

This email has internatiònal characters From: Tester Testee <ichaelmtest@gmail.com>

出于某种原因,它将From字段连接到第二个字段。但它确实能正确解码字符!两封电子邮件的标题顺序相同。当我取消对headers_encodedheader_code_pairs打印的注释时,我得到了:

Subject: This email has ASCII only From: Tester Testee

[('Subject: This email has ASCII only\r\nFrom: Tester Testee <ichaelmtest@gmail.com>\r\n\r\n', None)]

Subject: =?UTF-8?Q?This_email_has_internati=C3=B2nal_characters?= From: Tester Testee

[(b'Subject: ', None), (b'This email has internati\xc3\xb2nal characters', 'utf-8'), (b'From: Tester Testee <ichaelmtest@gmail.com>', None)]

所以在我看来,这个问题是由这样一个事实引起的,在国际示例中,decode_header在字段之间缺少一个CRFL。所以当make_header读取它时,它只看到一个字段。在

我可以通过在解码前分离头的行来解决这个问题,但是我是否遗漏了什么?有更好的方法吗?在

this old question的回答都没有解决我的示例中的问题,因此我将其作为我自己的问题发布,因为我有使用make_header的代码会产生不同的错误。如果您想在不使用真实邮箱的情况下重现错误,您应该能够将以下块粘贴到文本编辑器中,并让它加载它而不是data[0][1]

Subject: =?UTF-8?Q?This_email_has_internati=C3=B2nal_characters?=
From: Tester Testee <ichaelmtest@gmail.com>

Tags: fromcomnonedataemailthisgmailheader