2009-09-22 11 views
28

Python 2.6でRFC822メッセージが与えられた場合、どうすればを得ることができますか? text/plainコンテンツの部分ですか?基本的に、私が欲しいのアルゴリズムは、この次のとおりです。これらの事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パートからデコードされたテキストを取得する方法をかなりよく分かりません。

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

:私はtext/plainの部分にそれを呼び出すとき、私はエラーを取得するget_payload()を使用してエンコードテキストを取得、私はget_payload()方法のdecodeパラメータを使用しようとした場合(the docを参照)することができます加えて、私はHTMLを取ってテキストにできるだけ近づける方法を知らない。

+1

私はhttp://ginstrom.com/scribbles/2007/11/19/parsing-multilingual-email-with-に似たものに有益な解決策を見つけましたpython/ – beldaz

答えて

69

マルチパートの電子メールでは、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() 

は、真続いget_payload()の最初のパラメータ、(デコードフラグが第二パラメータである)としてNoneを渡す必要があります。 HTML部分の合理的なプレーンテキストの近似値を取得するために、私はhtml2textがうまくかなりくそ働くことがわかってきたように

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() 

:たとえば、私の電子メールは、MS Word文書の添付ファイルが含まれていると。

+1

+1、非常に明確かつ有用な説明。 –

+0

それは私が既に持っているものを正確にカバーする優れた説明です。私は、上記のように、部品の裸のペイロードを見つけて抽出することができます。しかし、デコードされていればそのパーツをデコードすることはできませんし、text/htmlパーツをtext/plainパーツがない場合はテキストにレンダリングすることもできません。 –

+0

(再読みに - 申し訳ありませんが、コーヒーは欠けています!)まあ、大丈夫です、あなたは私のHTMLをテキストの問題に解決しました:) –

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

これは、どの文字列が "正しい"ものであるかに関わらず、すべての 'text/plain '部分を盲目的に抽出します。 – tripleee

+0

@tripleee一般に、私たちは1つのプレーン、1つのhtmlパーツ、いくつかのイメージパーツを使用します。単純な部分以上のものがあっても、どちらが正しいかはどうやって分かりますか? – guneysus

+1

典型的なケースでは、トップレベルの 'multipart/alternative'があります。ここでは' text/plain'という部分が1つだけです。より一般的なケースでは、あなたのアプリケーションの目的と受信者の好みに依存するため、私は正しい答えは一つではないと思います。 – tripleee

関連する問題