46

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()を使用しようとすると(ドキュメントを参照)、テキスト/プレーン部分で呼び出すとエラーが発生します。decodeget_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を取得してテキストにできるだけ近づける方法がわかりません。

4

3 に答える 3

104

マルチパート電子メールでは、パートemail.message.Message.get_payload()ごとに1つのアイテムを含むリストを返します。最も簡単な方法は、メッセージを調べて、各部分のペイロードを取得することです。

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()、その後にTrueが続きます(デコードフラグは2番目のパラメーターです)。たとえば、私の電子メールにMSWord文書の添付ファイルが含まれているとします。

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がかなりうまく機能することがわかりました。

于 2009-09-22T23:17:31.193 に答える
2

フラットはネストよりも優れています;)

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 _
于 2015-12-02T10:06:28.697 に答える
0

@Jarret Hardieの優れた答えを追加するには:

私は個人的に、そのようなデータ構造を後で再利用できる辞書に変換するのが好きなので、次のようになります。ここで、content_typeはキーで、payloadは値です。

import email

[...]

email_message = {
    part.get_content_type(): part.get_payload()
    for part in email.message_from_bytes(raw_email).walk()
}

print(email_message["text/plain"])

于 2019-07-27T15:36:50.023 に答える