如何使用Python获取电子邮件的文本内容?

Chr*_*s R 36 python email mime rfc822

鉴于Python 2.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
Run Code Online (Sandbox Code Playgroud)

这些事,我get_mime_parthas_mime_part拍下来,但我不太清楚如何从MIME部分解码的文本.我可以使用编码文本get_payload(),但如果我尝试使用方法的decode参数get_payload()(请参阅doc),当我在text/plain部分调用它时会出现错误:

File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/
email/message.py", line 189, in get_payload
    raise TypeError('Expected list, got %s' % type(self._payload))
TypeError: Expected list, got <type 'str'>
Run Code Online (Sandbox Code Playgroud)

另外,我不知道如何使用HTML并尽可能地将其呈现为文本.

Jar*_*die 84

在多部分电子邮件中,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
Run Code Online (Sandbox Code Playgroud)

对于非多部分消息,无需进行所有步行.无论content_type如何,您都可以直接使用get_payload().

msg = email.message_from_string(raw_message)
msg.get_payload()
Run Code Online (Sandbox Code Playgroud)

如果内容是编码的,则需要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()
Run Code Online (Sandbox Code Playgroud)

至于获得HTML部分的合理纯文本近似,我发现html2text非常好用.

  • 实际上,使用part.get("content-transfer-encoding"),因为它只是一个标题.不属于content-type标头.另外,你可以使用`part.get_payload(decode = True)`来代替`part.get_payload(None,True)`,我认为它更清晰一些. (4认同)
  • 很酷..如何检查部件是否编码?我在哪里可以看到该部件的Content-Transfer-Encoding属性? (2认同)