如何获取电子邮件消息';使用Python创建文本内容?

如何获取电子邮件消息';使用Python创建文本内容?,python,email,mime,rfc822,Python,Email,Mime,Rfc822,给定Python2.6中的RFC822消息,如何获得正确的文本/普通内容部分?基本上,我想要的算法是: message = email.message_from_string(raw_message) if has_mime_part(message, "text/plain"): mime_part = get_mime_part(message, "text/plain") text_content = decode_mime_part(mime_part) elif has

给定Python2.6中的RFC822消息,如何获得正确的文本/普通内容部分?基本上,我想要的算法是:

message = email.message_from_string(raw_message)
if has_mime_part(message, "text/plain"):
    mime_part = get_mime_part(message, "text/plain")
    text_content = decode_mime_part(mime_part)
elif has_mime_part(message, "text/html"):
    mime_part = get_mime_part(message, "text/html")
    html = decode_mime_part(mime_part)
    text_content = render_html_to_plaintext(html)
else:
    # fallback
    text_content = str(message)
return text_content
在这些东西中,我有
get\u mime\u part
has\u mime\u part
,但我不太确定如何从mime部分获取解码文本。我可以使用
get\u payload()
获取编码文本,但是如果我尝试使用
get\u payload()
方法的
decode
参数(请参阅),我在文本/普通部分调用它时会出错:

File”/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/
“email/message.py”,get_有效载荷中第189行
raise TypeError('预期列表,获得%s'%type(self.\u有效负载))
TypeError:应为列表,已获取

此外,我不知道如何获取HTML并尽可能地将其呈现为文本。

在多部分电子邮件中,
email.message.message.get_payload()
返回一个列表,其中每个部分包含一个项目。最简单的方法是遍历消息并获取每个部分的有效负载:

import email
msg = email.message_from_string(raw_message)
for part in msg.walk():
    # each part is a either non-multipart, or another multipart message
    # that contains further parts... Message is organized like a tree
    if part.get_content_type() == 'text/plain':
        print part.get_payload() # prints the raw text
对于非多部分消息,无需执行所有遍历。无论内容类型如何,都可以直接获取_payload()

msg = email.message_from_string(raw_message)
msg.get_payload()
如果对内容进行编码,则需要将
None
作为第一个参数传递给
get_payload()
,然后是True(解码标志是第二个参数)。例如,假设我的电子邮件包含MS Word文档附件:

msg = email.message_from_string(raw_message)
for part in msg.walk():
    if part.get_content_type() == 'application/msword':
        name = part.get_param('name') or 'MyDoc.doc'
        f = open(name, 'wb')
        f.write(part.get_payload(None, True)) # You need None as the first param
                                              # because part.is_multipart() 
                                              # is False
        f.close()

至于获得HTML部分的合理的纯文本近似值,我发现这种方法非常有效。

扁平比嵌套好;)


要补充@Jarret Hardie的优秀答案:

我个人喜欢将这种数据结构转换为一个字典,以便以后可以重用,因此类似这样的东西,
content\u type
是关键,
payload
是值:

导入电子邮件
[...]
电子邮件={
part.get\u content\u type():part.get\u payload()
用于email.message_from_字节(原始电子邮件).walk()中的部分
}
打印(电子邮件[“文本/普通”])

这是一个很好的解释……完全涵盖了我已经得到的;如前所述,我可以定位并提取零件的裸有效载荷。但是,如果部分已解码,我就无法对其进行解码,如果没有文本/普通部分,我也无法将文本/html部分呈现为文本。(重读时——抱歉,缺少咖啡!)好吧,好吧,您已经解决了我的html到文本问题:)我的坏。。。昨晚我接电话时,显然没有足够的咖啡。我已经修改了答案,希望能符合你的需要。酷。。如何检查零件是否已编码?在哪里可以看到部件的内容传输编码属性?实际上,使用part.get(“内容传输编码”),因为它只是一个标题。不是内容类型标题的一部分。另外,你可以使用
part.get\u payload(None,True)
而不是
part.get\u payload(decode=True)
,我认为这更清楚一些。我发现了一个有用的解决方案,类似的方法是盲目地提取所有“text/plain”部分,而不注意哪一部分是“正确的”。@tripleee通常我们使用一个普通的,一个html部分,和几个图像部分。即使有不止一个普通部分,您如何知道哪一个是正确的?在典型情况下,对于顶级
多部分/备选方案
,其中只有一个部分是
文本/普通
,则是该部分。在更一般的情况下,我认为没有一个正确的答案,因为这取决于你申请的目的和接收者的偏好。公平地说,被接受的答案也有同样的问题。
msg = email.message_from_string(raw_message)
for part in msg.walk():
    if part.get_content_type() == 'application/msword':
        name = part.get_param('name') or 'MyDoc.doc'
        f = open(name, 'wb')
        f.write(part.get_payload(None, True)) # You need None as the first param
                                              # because part.is_multipart() 
                                              # is False
        f.close()
from email.mime.multipart import MIMEMultipart
assert isinstance(msg, MIMEMultipart)

for _ in [k.get_payload() for k in msg.walk() if k.get_content_type() == 'text/plain']:
    print _