确定MIME电子邮件部分是文件还是消息文本

4
作为一些电子邮件批处理的一部分,我们需要解码和“清理”消息。该过程的一个关键部分是将邮件正文与邮件附件分开。最棘手的部分是确定何时将“Content-Disposition: inline”部分视为消息正文替代或文件。
到目前为止,这段代码似乎处理了大多数情况:
from email import message_from_string

def split_parts(raw):
    msg = message_from_string(raw)
    bodies = []
    files = []

    for sub in msg.walk():
        if sub.is_multipart():
            continue
        cd = sub.get("Content-Disposition", "")
        if cd.startswith("attachment") or (cd.startswith("inline") and
                                           sub.get_filename()):
            files.append(sub)
        else:
            bodies.append(sub)

    return bodies, files

请注意,该代码依赖于内联部分在头部中指定文件名的情况,Outlook似乎对其所有的“multipart/related”消息都这样做。 “Content-ID”也可以用作提示,但根据RFC 2387,它不是这样的指示器。
因此,如果嵌入式图像被编码为具有“Content-Disposition:inline”的消息部分,并定义了“Content-ID”,并且没有文件名,则上述代码可能会错误地将其分类为消息正文替代品。
从我从RFC中读到的内容来看,在找到简单检查方面并没有太大希望(特别是由于按照RFC进行编码在现实世界几乎没有用处,因为没有人这样做);但我想知道误分类的可能性有多大。

原理

我可以有一组函数来处理每个multipart/*情况,并让它们间接递归。然而,我们并不太关心忠实的显示;事实上,我们会通过tidy过滤所有HTML消息。相反,我们更感兴趣的是选择一个消息正文的备选项并尽可能保存尽可能多的附件,即使它们被用于嵌入。

此外,某些用户代理在组合带有嵌入式附件(如PDF文件)的multipart/alternative消息时会出现非常奇怪的问题,这是由于用户将任意文件拖放到组合窗口中而导致的结果。


我认为没有一种标准的方法来做这件事。如果你想模拟客户端如何处理这些消息,可以实现自己的偏好来选择一组“multipart/alternative”中的一个部分(或者在实践中也可能是“multipart/mixed”、“multipart/related”等等),并将其他部分声明为“附件”。 - tripleee
1个回答

3

我不太明白你的意思,但是如果你需要正文内容,则我认为任何具有text/plain或text/html内容类型,带有内联内容配置且没有文件名或没有内容ID的都可以作为正文部分。


我仔细重新阅读了RFC 2387的第3.2节,我想我必须接受这样一个事实,即似乎没有人真正使用multipart/related容器的“start”参数。除非我找到一个需要我在我的小巧可爱的函数中增加复杂性的情况。 - C2H5OH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接