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
我认为它必须在Content-Type为multipart/mixed
且电子邮件内容为空的情况下执行某些操作,这将导致get_payload
返回str
。但是,我不确定,如果标准禁止这种EML(但是我有很多这样的示例),那是电子邮件模块中的错误,还是我使用了错误的代码。
答案 0 :(得分:1)
如果将策略更改为strict
:
Parser(policy=policy.strict).parse(eml_file)
解析器引发email.errors.StartBoundaryNotFoundDefect
,在docs中描述为:
StartBoundaryNotFoundDefect
–从未找到Content-Type标头中声明的起始边界。
如果您使用policy.default
解析消息并随后检查消息defects
,则它包含两个缺陷:
[StartBoundaryNotFoundDefect(), MultipartInvariantViolationDefect()]
MultipartInvariantViolationDefect
–一条消息声称是多部分的,但未找到任何子部分。请注意,当邮件有此缺陷时,即使其内容类型声称是多部分的,其is_multipart()方法也可能返回false。
StartBoundaryNotFoundDefect
的结果是解析器终止解析并将消息有效负载设置为到目前为止已捕获的主体-在这种情况下,什么也没有,因此有效负载为空字符串,从而导致异常您在运行代码时看到的。
可以说,在调用list
之前,Python不检查有效载荷是否为copy()
是一个错误。
在实践中,您必须通过将附件的迭代包装在try/except
中,对msg.defects
的内容进行条件迭代或使用policy.strict
进行解析并丢弃所有消息来处理这些消息。报告缺陷的消息。