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

问题描述:

在Python 2.6中给出了一个RFC822消息,我如何才能获得正确的文本/纯文本内容部分?基本上,该算法我想是这样的:如何使用python获取电子邮件的文本内容?

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_mime_parthas_mime_part拍下来,但我不太清楚如何从MIME部分解码的文本。我可以使用get_payload()编码文本,但如果我尝试使用get_payload()方法的decode参数(见the doc)我得到一个错误,当我把它的纯文本/部分:

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'> 

另外,我不知道如何将HTML呈现得尽可能接近文本。

+1

我发现类似的东西有用的解决方案http://ginstrom.com/scribbles/2007/11/19/parsing-multilingual-email-with- python/ – beldaz 2013-07-11 03:21:43

在多部分电子邮件中,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 

对于非多的消息,没有必要做所有的步行。无论content_type如何,您都可以直接转到get_payload()。

msg = email.message_from_string(raw_message) 
msg.get_payload() 

如果该内容被编码,则需要通过None作为第一个参数,以get_payload(),随后真(解码标记是第二个参数)。例如,假设我的电子邮件中包含的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部分的合理纯文本逼近,我发现html2text作品相当不错的好。

+1

+1,非常明确有用的解释。 – 2009-09-23 03:11:09

+0

这是一个很好的解释......它涵盖了我已经得到的东西;如上所述,我可以找到并提取零件的裸露有效载荷。但是,如果解码了部分,我就不能解码该部分,如果没有文本/纯色部分可用,我也不能将文本/ html部分渲染为文本。 – 2009-09-23 13:45:36

+0

(关于重读 - 对不起,咖啡是缺乏!)好吧,好吧,所以你已经解决了我的HTML到文本问题:) – 2009-09-23 13:46:16

扁平比嵌套好;)

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 _ 
+0

这个盲目地提取所有的“文本/平原”部分,不关注哪一个是“正确的”。 – tripleee 2015-12-02 10:11:15

+0

@tripleee通常我们使用一个普通,一个html部分和几个图像部分。即使不是普通的部分,你怎么知道哪一个是正确的? – guneysus 2015-12-02 22:28:55

+1

在典型的情况下,使用*'multipart/alternative',其中只有一个部分是'text/plain',就是那个。在更一般的情况下,我不认为有一个正确的答案,因为它取决于您的应用程序的目的和收件人的偏好。 – tripleee 2015-12-03 05:24:58