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

50 投票
5 回答
79473 浏览
提问于 2025-04-15 14:31

在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

在这些内容中,我已经掌握了get_mime_parthas_mime_part的用法,但我不太确定怎么从MIME部分获取解码后的文本。我可以通过get_payload()获取到编码后的文本,但如果我尝试使用get_payload()方法的decode参数(可以查看文档),在处理文本/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'>

另外,我也不知道怎么把HTML内容转换成尽可能接近文本的格式。

5 个回答

1

试试我这个用于IMAP的库:https://github.com/ikvk/imap_tools

from imap_tools import MailBox, AND

# Get date, subject and body len of all emails from INBOX folder
with MailBox('imap.mail.com').login('test@mail.com', 'pwd') as mailbox:
    for msg in mailbox.fetch():
        print(msg.date, msg.subject, len(msg.text or msg.html))

看看html2text这个工具:https://pypi.org/project/html2text/

也许msg.text就足够了

1

简单的比复杂的好;)

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 _
111

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

如果邮件不是多部分的,就不需要遍历了。你可以直接调用 get_payload(),不管内容类型是什么。

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

如果内容是经过编码的,你需要在调用 get_payload() 时,第一个参数传入 None,第二个参数传入 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 部分获取一个合理的纯文本版本,我发现 html2text 的效果非常不错。

撰写回答