Python 3.6 电子邮件模块崩溃并显示此错误:
Traceback (most recent call last):
File "empty-eml.py", line 9, in <module>
for part in msg.iter_attachments():
File "/usr/lib/python3.6/email/message.py", line 1055, in iter_attachments
parts = self.get_payload().copy()
AttributeError: 'str' object has no attribute 'copy'
崩溃可以用这个EML文件重现,
From: "xxx@xxx.xx" <xxx@xxx.xx>
To: <xx@xxx.xx>
Subject: COURRIER EMIS PAR PACIFICA
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_3181_1274694650.1556805728023"
Date: Thu, 2 May 2019 16:02:08 +0200
还有这段最小的代码:
from email import policy
from email.parser import Parser
from sys import argv
with open(argv[1]) as eml_file:
msg = Parser(policy=policy.default).parse(eml_file)
for part in msg.iter_attachments():
pass
我相信它必须与内容类型multipart/mixed
以及电子邮件内容为空有关,这会导致get_payload
返回str
。但是,我不确定,如果标准禁止这样的 EML(但我有很多这样的样本),这是电子邮件模块中的错误,或者我使用的代码错误。
如果将策略更改为strict
:
Parser(policy=policy.strict).parse(eml_file)
解析器引发email.errors.StartBoundaryNotFoundDefect
,在文档中描述为:
StartBoundaryNotFoundDefect
– 从未找到内容类型标头中声明的起始边界。
如果使用policy.default
解析消息并在事后检查其defects
,则它包含两个缺陷:
[StartBoundaryNotFoundDefect(), MultipartInvariantViolationDefect()]
MultipartInvariantViolationDefect
– 一条消息声称是多部分,但未找到子部分。请注意,当邮件具有此缺陷时,即使其内容类型声称是多部分,其 is_multipart() 方法也可能返回 false。
StartBoundaryNotFoundDefect
的结果是,分析器终止分析并将消息有效负载设置为到目前为止捕获的正文 - 在本例中为无内容,因此有效负载为空字符串,从而导致运行代码时看到的异常。
可以说,Python 在调用 payload 之前不会检查有效负载是否是list
copy()
这一事实是一个错误。
实际上,您必须通过将附件的迭代包装在try/except
中,对msg.defects
的内容进行迭代,或者使用policy.strict
解析并丢弃所有报告缺陷的消息来处理这些消息。