Как я могу получить текст сообщения электронной почты, используя Python? - PullRequest
33 голосов
/ 23 сентября 2009

Учитывая сообщение RFC822 в Python 2.6, как я могу получить правильный текстовый / простой контент? В основном, алгоритм, который я хочу, состоит в следующем:

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_part и has_mime_part, но я не совсем уверен, как получить декодированный текст из части MIME. Я могу получить кодированный текст , используя get_payload(), но если я пытаюсь использовать параметр decode метода get_payload() (см. документ ), я получаю сообщение об ошибке, когда Я называю это по тексту / простой части:

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 и как можно точнее отобразить его в тексте.

Ответы [ 2 ]

80 голосов
/ 23 сентября 2009

В составном электронном письме 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 (), независимо от content_type.

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-части, я обнаружил, что html2text работает чертовски хорошо.

1 голос
/ 02 декабря 2015

Квартира лучше вложенной;)

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