moblog

一つ上に移動 moblog
携帯からの投稿です

テストぷり

06-09-18_17-16.jpg

テストですお

カテゴリ
moblog moblog
トラックバック用URL:
http://nagosui.org:8080/Nagosui/COREBlog2/moblog2006-10-02-23-02/tbping

moblog奮闘記1

手順の確認

moblogに必要なファイルを入手する

moblogをするための準備をします。まずは柴田さんの書いたスクリプトを拝借してきます(moblog.pyおよびadd_moblog_entry.py)。これらは以下のようなファイルです。

moblog.py
メールサーバにアクセスして画像やら何やらをごにょごにょします。COREBlog2が稼働しているサーバのホームディレクトリなどに置いて、cronなどで定期的に実行するファイルです。
add_moblog_entry.py
実際にCOREBlog2にエントリを投稿する本体です。ZMIから「Ploneインスタンス/portal_skins/custom」へScript(Python) としてアップロードします。アップロードする際には「.py」をつけてはいけません。

moblog.pyを編集する

素のmoblog.pyはメールサーバがAPOP認証を行うことを前提に書かれています。少し編集することでAPOPに対応していないサーバでも使うことができます。

編集する必要があるのは2カ所あります。

まずは100行目付近の以下の部分です。

95    #
96    # Please set some information,(host of mail server,etc) to use
97    #
98
99    import poplib
100   s = poplib.POP3('host.of.mail.server')
101   s.apop('yourmailaccount','mailpassword')

APOPに対応しているメールサーバを利用する場合は100行目、101行目をそのまま編集すればよいでしょう。例えば以下のようにします。

100   s = poplib.POP3('mail.example.com')
101   s.apop('nyusuke','hogehoge')

APOPに対応していないメールサーバを利用する場合は101行目をコメントアウトし、その後に以下のような変更を加えます。

100   s = poplib.POP3('host.of.mail.server')
101   # s.apop('yourmailaccount','mailpassword') ←ここはコメントアウト
102 s.user('nyusuke')  ←アカウント名
103 s.pass_('hogehoge') ←パスワード

もう一カ所編集する部分があります。106行目付近にある以下の部分です。

106        msgbody = '\n'.join(m[1])
107        add_moblog_entry(msgbody,
108         'http://[user]:[pass]@url.of.blog/path2/blog/','password4mail')

上記の108行目を編集します。内容は以下のようになります。

[user]
Ploneのユーザ名
[pass]
Ploneのパスワード
url.of.blog/path2/blog/
COREBlog2までのパス
password4mail
moblog用の秘密の暗号(何でもよい)

例えば以下のようになります。

108         'http://nyusuke:fugafuga@nagosui.org/Nagosui/COREBlog2/','entrymoblog')

半角の括弧、すなわち”[”や”]”は必要ありません。

また、

COREBlog2までのパスの最後にはスラッシュ”/”が必要です。

編集が終了したらこのスクリプトをホームディレクトリなどに置いておきましょう。

$ mv ./moblog.py /home/nyusuke/moblog.py

add_moblog_entry.pyをPloneにアップロードする

add_moblog_entry.pyは特に編集する必要はありません。ZMIから「/Ploneインスタンス/portal_skins/custom」へ行き、画面右上のプルダウンメニューから「Script(Python)」を選び、idを「add_moblog_entry」として追加します(下図参照)。

拡張子の部分、すなわち「.py」を付けないように注意してください。

add_moblog_entryを追加する

COREBlog2の準備

準備というほどのものではありませんが、

  • moblogというidのカテゴリ
  • imagesというidのフォルダ

が必要です。

携帯からエントリする

上記の設定が終わったら実際に携帯から投稿してみます。宛先、件名、添付ファイルなどは問題ないと思いますが、本文には注意が必要です。本文は以下のように入力してください。

  • 本文1行目:moblog.pyの108行目で設定した秘密の暗号。これがmoblog.pyのものと一致しないとエントリが投稿されません。
  • 本文2行目:投稿されるエントリの、カテゴリのidを指定します。空の場合はmoblogカテゴリになります。
  • 本文3行目以降:エントリの本文になります。

ですので、例えば以下のようになります。

entrymoblog

実家の猫、「道」ちゃんです。

このような内容のメールを携帯から送った後、ホームディレクトリに置いたmoblog.pyを実行すればCOREBlog2にエントリが投稿されるはずです。

参考エントリ

以下のエントリが参考になります。

以前はsakaさんがmoblogについての有用なドキュメントを残していてくれたのですが、自サーバを停止し、移転後は何故かrestがうまくいってないらしく、現在ドキュメントへのリンクは切れています。

運用例:Yahooメールアカウントを利用してmoblogする

Yahooアカウントの取得とmoblogするためのメールの設定

ウチのメールサーバではimapを使っていますので、このままではmoblogできません。かといってPOPサーバを導入するのもめんどくさいし、moblogだけのためにそこまでやるのもなぁ、ということでYahooメールを使ってmoblogしてみます。

Yahooへ行ってアカウントをとったあと、Yahooメール使い方ガイドを見ながらPOPとして利用するための設定を行います。ステップ8のアカウントのまとめはmoblog設定に便利ですのでプリントアウトして手元に置いておくと良いでしょう。

以下のようになるはずです(アカウントなどは仮のものです)。

  • 受信メール(POP3サーバー):pop.mail.yahoo.co.jp
  • 受信メール(SMTP)サーバー:smtp.mail.yahoo.co.jp
  • アカウント名/ログイン名:nyusuke_moblog
  • メールアドレス:nyusuke_moblog@yahoo.co.jp
  • パスワード:nyusukemoblog

moblog.pyの編集

アカウントの準備が整ったので、上述のmoblog用のスクリプトをダウンロードし、moblog.pyを編集します。

Yahooメールアカウント以外で編集に必要な項目を以下のように仮定します。

  • Ploneのアカウント:nyusuke
  • Ploneのパスワード:nyusukeplone
  • COREBlog2のパス:http://nagosui.org/Nagosui/COREBlog2/
  • moblog用の秘密の暗号:entrymoblog

ということでmoblog.pyは以下のようになります。

100    import poplib
101    s = poplib.POP3('pop.mail.yahoo.co.jp') ← YahooのPOPサーバ
102    # s.apop('yourmailaccount','mailpassword') ← APOPは使わないのでコメントアウト
103    s.user('nyusuke_moblog') ← Yahooのアカウント名
104    s.pass_('nyusukemoblog') ← Yahooのパスワード
105    l = s.list()
106    if len(l) and l[1]:
107        m = s.retr(1)
108
109        msgbody = '\n'.join(m[1])
110        add_moblog_entry(msgbody,
111         'http://nyusuke:nyusukeplone@nagosui.org/Nagosui/COREBlog2/','entrymoblog') ← COREBlog2のパスと秘密の暗号

スクリプトの設置

moblog.pyはホームディレクトリに置いておくことにします。

$ mv ./moblog.py /home/nyusuke/moblog.py

add_moblog_entry.pyは上述したようにPloneのcustomにアップロードします。

またCOREBlog2にmoblogカテゴリとimagesフォルダを作成しました。

imagesフォルダはおそらく存在していると思いますが、何故かimagesフォルダがない、という場合にはこちらを参考にしてください。

cronへの登録

定期的にmoblog.pyを実行する(Yahooメールに新着のmoblogメールが無いかどうか確認する)ためにcronへ登録します。

まずはmoblog.pyを実行可能にしておきます。

$ chmod 755 /home/nyusuke/moblog.py

cronへ登録します。ここでは10分ごとにメールをチェックするように設定しましょう。

$ crontab -e
  0-59/10 * * * * /home/nyusuke/moblog.py

携帯から投稿する

  • 宛先:nyusuke_moblog@yahoo.co.jp
  • 件名:テストぷり
  • 添付:06-09-18_17-16.jpg
  • 本文1行目:entrymoblog
  • 本文2行目:
  • 本文3行目:テストですお

としてメールを送信すると、このエントリのようになります。

トラックバック用URL:
http://nagosui.org:8080/Nagosui/COREBlog2/fight-for-moblog-1/tbping

Re:moblog奮闘記1

投稿者 saka 投稿日時: 2006年10月06日 06時00分

ごぶさたしてます。
objectis.netは、自分の設定のせいなのか何だかよくわからない状況です(笑)moblog.pyは複数画像の添付とか画像無しをOKに改造したような思い出が…他にホスティングがないかなあ。

Re:moblog奮闘記1

投稿者 nyusuke 投稿日時: 2006年10月06日 10時34分

freezope.orgはどうなのかなぁ、って今確認してみたら
なんかProxyErrorでregisterできなかったです…

moblog奮闘記番外編 - emailモジュール

moblog.pyを読んで、さらにいじれるようになることを目標にがんばるためには、とりあえずemailモジュールその他について整理しておかないといけないと思いました。

Eメールの構造

emailモジュールを見てみる前に、そもそもEメールはどのような構造をしているのでしょうか。

Eメールは大きく分けてヘッダと本文という二つのパーツからなっています。ヘッダには送信者のメールアドレスや送信先のメールアドレスなど、メールを送るために必要な情報が含まれています。そして本文はもちろんそのメールの内容です。ヘッダと本文は改行で区切られています。

Return-Path: <nyusuke@example.com>
Delivered-To: nagosui@example.com
From: nyusuke@example.com
To: nagosui@example.com
Subject: =?iso-2022-jp?B?GyRCJF8kcyRKJE4bKEJQeXRob24=?=
Message-ID: <E8142EF2F595FEAEFC0@example.com>
Date: Mon, 6 Nov 2006 01:13:12 +0900
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-2022-jp; ←ここまでヘッダ

テストメールです。 ←ここから本文
テストです。

テストなんです。

画像等の添付ファイルがあった場合には構造が少し違ってきます。上記の本文のパーツの部分が複数にわかれ、本文のデータや画像のデータ等が個々のパーツに分けられます。このような構造を「マルチパート」と呼びます。マルチパート形式のメールの本文や画像データ等のパーツは「boundary」(つまり境界線)と呼ばれる文字列によって区切られています。

次の例ではヘッダの最後の部分において、このメールがマルチパートであること、そして境界線として「-------=_NextPart_57559_22154_52285」という文字列を使用していることが述べられています。そして実際その後に、「-------=_NextPart_57559_22154_52285」で区切られた本文と画像データが続いています。

Return-Path: <nyusuke@example.com>
Delivered-To: nagosui@example.com
From: nyusuke@example.com
To: nagosui@example.com
Subject: =?iso-2022-jp?B?GyRCJF8kcyRKJE4bKEJQeXRob24=?=
Message-ID: <E8142EF2F595FEAEFC0@example.com>
Date: Mon, 6 Nov 2006 01:13:12 +0900
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="-----=_NextPart_57559_22154_52285"

-------=_NextPart_57559_22154_52285
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit

添付ファイルのあるテストメール。

-------=_NextPart_57559_22154_52285
Content-Type: image/jpeg; name="test.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.jpg"

/9j/4QJqRXhpZgAATU0AKgAAAAgACwEOAAIAAAAPAAAAvgEPAAIAAAAIAAAA3AEQAAIAAAAFAAAA


-------=_NextPart_57559_22154_52285--

マルチパートか否かで構造が変わってくる点に注意ですね。

Messageクラス

emailモジュールはメールをほげほげするのにとても便利なMessageクラスを提供してくれるようです。すなわち基本的な流れとしては、poplibによってゲッツしたメールだとかファイルやら文字列やらからMessageオブジェクトへ変換し、それをほげほげする、という形になるのではないでしょうか。

Messageオブジェクト

Messageオブジェクトはヘッダとペイロードというパーツを持っています。ペイロードというのは「ヘッダ以外の部分」を指す言葉で、まぁ本文と考えてだいたい合っているのではないでしょうか(マルチパートのEメールの場合は本文以外にも画像データなどが含まれます)。

試しにファイルからMessageオブジェクトを作ってみます。

>>> import email
>>> message = email.message_from_file(open('message.txt'))
>>> message
<email.Message.Message instance at 0x00CA4918>

2行目のmessage_from_file()はファイルオブジェクトからMessageオブジェクトに変えてくれるメソッドです。ファイルシステム上にあるmessage.txtというテキストファイルをopen()メソッドによってファイルオブジェクトとして開き、これをMessageオブジェクトへ変換、messageという変数に代入しました。中身はas_string()メソッドを使えば文字列として見ることができるでしょう。

>>> message.as_string()
'Return-Path: <nyusuke@example.com>\nDelivered-To: nagosui@example.com\nFrom: ny
usuke@example.com\nTo: nagosui@example.com\nSubject: =?iso-2022-jp?B?GyRCJF8kcyR
KJE4bKEJQeXRob24=?=\nMessage-ID: <E8142EF2F595FEAEFC0@example.com>\nDate: Mon, 6
Nov 2006 01:13:12 +0900\nMime-Version: 1.0\nContent-Type: text/plain; charset=i
so-2022-jp;\n\n\x83e\x83X\x83g\x83\x81\x81[\x83\x8b\x82\xc5\x82\xb7\x81B\n\x83e\
x83X\x83g\x82\xc5\x82\xb7\x81B\n\n\x83e\x83X\x83g\x82\xc8\x82\xf1\x82\xc5\x82\xb
7\x81B'

ヘッダをいじる

Messageオブジェクトのヘッダは辞書形式でいじることができますので、has_key()、keys()、values()、items()、get()などおなじみのメソッドが利用できます。

# keys()はヘッダフィールドをリストとして返します
>>> message.keys()
['Return-Path', 'Delivered-To', 'From', 'To', 'Subject', 'Message-ID', 'Date', '
Mime-Version', 'Content-Type']
# items()はフィールドとその値のタプルをリストとして返します
>>> message.items()
[('Return-Path', '<nyusuke@example.com>'), ('Delivered-To', 'nagosui@example.com
'), ('From', 'nyusuke@example.com'), ('To', 'nagosui@example.com'), ('Subject',
'=?iso-2022-jp?B?GyRCJF8kcyRKJE4bKEJQeXRob24=?='), ('Message-ID', '<E8142EF2F595
FEAEFC0@example.com>'), ('Date', 'Mon, 6 Nov 2006 01:13:12 +0900'), ('Mime-Versi
on', '1.0'), ('Content-Type', 'text/plain; charset=iso-2022-jp;')]
# get()は指定したフィールドの値を返します
>>> message.get('From')
'nyusuke@example.com'

ヘッダをもっといじる

例えば件名には日本語がよく利用されます。しかしget()などで得られる値はそのままでは意味不明なので加工してやる必要があります。

>>> message.get('Subject')
'=?iso-2022-jp?B?GyRCJF8kcyRKJE4bKEJQeXRob24=?=' ←意味不明

これを何とかするのに便利なのが、email.Headerモジュールのdecode_header()メソッドです。decode_header()は文字セットを変更せずにヘッダをデコードし、デコードされた文字列とエンコード名からなるタプルを返します。

>>> import email.Header
>>> subject = message.get('Subject')
>>> email.Header.decode_header(subject)
[('\x1b$B$_$s$J$N\x1b(BPython', 'iso-2022-jp')] ←タプルが入ったリスト

ということは以下のようにすればデコードされた文字列とエンコードを取り出すことができます。

# リストの最初の要素であるタプルの、最初の要素を取り出す
>>> d_subject = email.Header.decode_header(subject)[0][0]
>>> d_subject
'\x1b$B$_$s$J$N\x1b(BPython'

# リストの最初の要素であるタプルの、1番目の要素を取り出す
>>> enc = email.Header.decode_header(subject)[0][1]
>>> enc
'iso-2022-jp'

ということはこれらをもとにして意味のある文字列としての件名を得ることができます。

# ユニコード文字列に変換
>>> u_subject = unicode(d_subject, enc)
>>> u_subject
u'\u307f\u3093\u306a\u306ePython'

# エスケープされるのを回避するためにprintableで出力
>>> print u_subject
みんなのPython

ペイロードをいじる

ペイロードの構造はマルチパートか否かで変わってきますので注意が必要です。ペイロードを得るためにはget_payload()メソッドを使います。非マルチパートなメールの場合ペイロードは文字列となりますが、マルチパートメッセージの場合は「Messageオブジェクトのリスト」になります。

# 非マルチパートメッセージの場合は文字列
>>> msg_not_multi = email.message_from_file(open('message2.txt'))
>>> msg_not_multi.get_payload()
'\x1b$B%F%9%H%a!<%k$G$9!#\x1b(B\n\x1b$B%F%9%H$G$9!#\x1b(B\n\n\x1b$B%F%9%H$J$s$G$
9!#\x1b(B'

# マルチパートメッセージの場合はMessageオブジェクトのリスト
>>> msg_multi = email.message_from_file(open('message3.txt'))
>>> msg_multi.get_payload()
[<email.Message.Message instance at 0x00CE7F08>, <email.Message.Message instance
at 0x00CE7F30>]

非マルチパートメッセージのペイロード

非マルチパートの場合は文字列が返ってきますので扱いはさほど面倒ではないように見えます。問題はエンコードですが、get_content_charset()というメソッドがありますので、これを利用してユニコード文字列に変換したりすれば扱いもらくちんなのではないでしょうか。

# エンコードを得る
>>> msg_not_multi.get_content_charset()
'iso-2022-jp'

# ユニコード文字列に変換して表示してみる
>>> u_body_nm = unicode(msg_not_multi.get_payload(), msg_not_multi.get_content_charset())
>>> print u_body_nm
テストメールです。
テストです。

テストなんです。

マルチパートメッセージのペイロード

一般的なマルチパートを考えるときりがないので、moblogの場合だけに範囲をしぼって考えたいと思います。

携帯電話から添付画像付きのメールを送った場合にはメールのサブパートは

  • メール本文
  • 画像1
  • 画像2
  • 画像n

という感じになるはずです。そしてこれらのサブパートそれぞれがMessageオブジェクトとして存在しています。

マルチパートメッセージのMessageオブジェクトに対してget_payload()すると、これらのリストが返ってくるわけですね。ということは、

  • msg_multi.get_payload[0]→Messageオブジェクト(メール本文)
  • msg_multi.get_payload[1]→Messageオブジェクト(画像1)
  • msg_multi.get_payload[2]→Messageオブジェクト(画像2)

のようにそれぞれを取り出すことができます。

各サブパートはMessageオブジェクトですから、例えばメール本文部分は以下のような構造を持つMessageオブジェクトです。

Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit ←ここまでヘッダ

添付ファイルのあるテストメール。 ←ここからペイロード

画像は以下のような構造になります。

Content-Type: image/jpeg; name="test.jpg"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.jpg" ←ここまでヘッダ

/9j/4QJqRXhpZgAATU0AKgAAAAgACwEOAAIAAAAPAAAAvgEPAAIAAAAIAAAA3AEQAAIAAAAFAAAA ←ここからペイロード
AAAIAAAA3AEQAAIAAA  Base64でエンコードされた画像データが続く  AgACwEOAAIAAAAPA
EQAAIAAAAF/9j/4QJqRXhpZgAATU0AKgAAIAAAAPAAAAvgEPAAIAAAAIAAAA3AEQAAIAAAAFAAAA

本文の部分のペイロードを得るにはmsg_multi.get_payload[0]に対してget_payload()してやればいいですよね。

>>> msg_multi.get_payload()[0].get_payload()
'\x1b$BE:IU%U%!%$%k$N$"$k%F%9%H%a!<%k!#\x1b(B\n'

扱いやすくするためにエンコードをゲッツして、ユニコード文字列に変換します。

>>> body_multi = msg_multi.get_payload()[0].get_payload()
>>> enc_multi = msg_multi.get_payload()[0].get_content_charset()
>>> u_body_m = unicode(body_multi, enc_multi)
>>> print u_body_m
添付ファイルのあるテストメール。

画像の方はBase64でエンコードされていますが、get_payload()にはdecodeというオプションがあります。これは12.2.1 電子メールメッセージの表現によれば

オプションの decode はそのペイロードが Content-Transfer-Encoding: ヘッダに従って デコードされるべきかどうかを指示するフラグです。

ということです。

添付画像をほげほげする場合には画像の生データが欲しいわけで、画像のMessageオブジェクトには(おそらく)「Content-Transfer-Encoding: base64」があるので、これを信用してしまってdecodeオプションをつけてやれば生データを得ることができるのではないでしょうか。

# decode=1を指定してget_payload()する
>>> msg_multi.get_payload()[1].get_payload(decode=1)
'\xff\xd8\xff\xe1\x02jExif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x0b\x01\x0e\x00\x0
2\x00\x00\x00\x0f\x00\x00\x00\xbe\x01\x0f\x00\x02\x00\x00\x00\x08\x00\x00\x00\xd
c\x01\x10\x00\x02\x00\x00\x00\x05\x00\x00\x00(以下ずーっと続く)'

マルチパートメッセージのサブパートを表示してみる

以上をふまえて、マルチパートメッセージのサブパートであるメール本文と画像のデータを表示してみます。

マルチパートメッセージの構造をまとめておきましょう。下図では画像が1枚添付されているメールを想定しています。

マルチパートメッセージの構造

ここで取り出したいのは、「ペイロード:メール本文」と「ペイロード:画像データ」です。図は画像が1枚だけ添付された状態ですが、実際には2枚、3枚と画像を添付したくなってしまう場合もあると思います。こういった状況に柔軟に対応するためにはwalk()メソッドを使うと便利です。

walk()メソッド

walk()メソッドはメッセージオブジェクトツリー中のすべてのパートおよびサブパートを渡り歩き、forループと一緒に使うと便利なメソッドです。上図のメッセージオブジェクトツリーは以下のようになります。

  • Messageオブジェクト(全体)
    • Messageオブジェクト(メール本文)
    • Messageオブジェクト(画像データ)
このオブジェクトツリーを順に渡り歩いて処理を行います。例えば
# マルチパートメッセージのファイルを開いてMessageオブジェクトを作る
msg_multi = email.message_from_file(open('msg_multi.txt'))

# メッセージの各部分に対して処理を行う
for part in msg_multi.walk():
    part.処理

などとすると、まずオブジェクトツリーのトップにある「Messageオブジェクト(全体)」に対して処理が行われ、次にその下層の一番上にある「Messageオブジェクト(メール本文)」に対して処理が行われ、最後に「Messageオブジェクト(画像データ)」に対して処理が行われます。

例えば

for part in msg_multi.walk():
    print part.get_payload()

とすれば、それぞれのMessageオブジェクトのペイロードを順番に表示します。結果は以下のようになります。

# Messageオブジェクト(全体)のペイロードを表示
# マルチパートメッセージなのでMessageオブジェクトのリストが返ってくる
[<email.Message.Message instance at 0x00C07AF8>, <email.Message.Message instance
 at 0x00C07A80>]

# Messageオブジェクト(メール本文)のペイロードを表示
$BE:IU%U%!%$%k$N$"$k%F%9%H%a!<%k!#(B

# Messageオブジェクト(画像データ)のペイロードを表示
/9j/4QJqRXhpZgAATU0AKgAAAAgACwEOAAIAAAAPAAAAvgEPAAIAAAAIAAAA3AEQAAIAAAAFAAAA
(以下画像データが続く)

もちろん添付画像が複数あればそれらに対して順に処理を行います。

実際の処理を考える

さてサブパートを表示させることを考えると、forループとifを使えばうまくいきそうです。

  1. Messageオブジェクト(全体)は特に表示させるものもないのでスルーする
  2. Messageオブジェクト(メール本文)のペイロードをゲッツして、ユニコード文字列に変換して表示する
  3. Messageオブジェクト(画像データ)のペイロードをゲッツして、生データに変換して表示する

という流れにしてみます。

ループ中の当該Messageオブジェクトが全体か、メール本文か、画像データかは、当該オブジェクトのコンテンツタイプをチェックして判別します。

  • Messageオブジェクト(全体)→'multipart/mixed'
  • Messageオブジェクト(メール本文)→'text/plain'
  • Messageオブジェクト(画像データ)→'image/jpg'

となるはずですので、それぞれのコンテンツタイプのメインタイプ(スラッシュの前の部分)で分岐させてます。メインタイプはget_content_maintype()メソッドから得ることができます。

for part in msg_multi.walk():

# Messageオブジェクト(全体)に対しては何もしないのでcontinue
    if part.get_content_maintype() == 'multipart':
        continue

# Messageオブジェクト(メール本文)に対しては
# ペイロード(メール本文)をユニコード文字列にして表示
    elif part.get_content_maintype() == 'text':
        body = subpart.get_payload()
        enc = subpart.get_content_charset()
        u_body = unicode(body, enc)
        print u_body

# Messageオブジェクト(画像データ)に対しては
# 生データに変換してから表示
    elif part.get_content_maintype() == 'image':
        r_img = subpart.get_payload(decode=1)
        print r_img

結果は以下のような感じ。

# メール本文
添付ファイルのあるテストメール。

# 画像データ
リ・jExif MM
(以下画像データが続く)

さてこれほどPythonをいじったのは初めてなんですが、moblog.pyを読めるようになったでしょうか…。

カテゴリ
Python Python
moblog moblog
トラックバック用URL:
http://nagosui.org:8080/Nagosui/COREBlog2/fight-for-moblog-extra-email-module/tbping

moblog奮闘記2-1

moblog.pyを読んでみよう!

moblog.pyの構造

moblog.pyはモジュールをインポートする部分、関数を定義する部分(3つ)、関数を実行する部分に分かれています。

moblog-py

実際に実行されるのは最後にあるmain()だけですが、main()を実行する際にadd_moblog_entry()が、add_moblog_entry()を実行する際にget_parts()が呼ばれます。

main()の中身

main()は比較的短い関数で、携帯電話からメールサーバに送られたメールを読みとってCOREBlog2へ投稿するためのものです。モジュールとしてpoplibを利用しています。

poplibを使ってみる

試しにpoplibを使ってみます。poplibはPOP3クラスを提供してくれます。

このクラスが、実際にPOP3プロトコルを実装します。インスタンスが初期化 されるときに、コネクションが作成されます。 port が省略されると、POP3標準のポート(110)が使われます。

POP3オブジェクトにはログインするためのuser()、pass_()メソッドがあります。yahooのメールサーバにログインしてみます。

>>> import poplib
>>> p3 = poplib.POP3("pop.mail.yahoo.co.jp")
>>> p3.user("yahooのid")
'+OK password required.'
>>> p3.pass_("yahooのpass")
'+OK maildrop ready, 1 message (1290 octets) (1290 1073741824)'

user()メソッドはパスワード要求を返し、pass_()メソッドはメッセージ数とメールボックスサイズを返します。

実際にメールを取り出してみます。取り出すにはretr()メソッドを使います。引数には何番目のメッセージを取り出すかを与えます。

>>> p3.retr(1)
('+OK 742 octets', ['From: hogehoo@example.com', 'To: fugafuu@example.com', 'Sub
ject: =?iso-2022-jp?B?GyRCJEYkOSRIGyhC?=', ..., 'Date: Thu, 16 Nov 2006 23:07:50
 +0900', 'Mime-Version: 1.0', 'Content-Type: text/plain; charset="iso-2022-jp"',
 'Content-Transfer-Encoding: 7bit', '', '\x1b$B$U$,$U$,\x1b(B', '\x1b$B$W$j$W$j\
x1b(B'], 742)

上記は(個人情報に関する部分などを削除したり書き換えたりして)ちょっと手を入れていますが、retr()メソッドを使ったときに返ってくるのは3つの要素を持った下記のようなタプルになることがわかります。

  • 0番目の要素:サーバからの応答文字列
  • 1番目の要素:メール本体の内容が1行ごとに分割されて含まれたリスト
  • 2番目の要素:メッセージのサイズ

ということはこの1番目の要素を取り出せば、メッセージの内容を得ることができます。

# p3_messageにメッセージの内容を代入
>>> p3_message = p3.retr(1)[1]

quit()メソッドを使うと接続を切断します。

>>> p3.quit()
'+OK server signing off.'

main()の中身(前半)

前半は以下のようになっています。

def main():

    #
    # Please set some information,(host of mail server,etc) to use
    #

    import poplib
    s = poplib.POP3('host.of.mail.server')
    s.apop('yourmailaccount','mailpassword')
l = s.list()

apop()メソッドはAPOP認証機能を提供してくれますが、すべてのサーバがAPOPに対応しているわけではありません。そこでPOP3でログインするために上述したuser()メソッドおよびpass_()メソッドを使ってapop()メソッドを置き換えてみましょう。

def main():

    #
    # Please set some information,(host of mail server,etc) to use
    #

    import poplib
    s = poplib.POP3('host.of.mail.server')
s.user('mailaccount')
s.pass_('mailpassword')
l = s.list()

前半部の最後の部分ではlist()メソッドを使っています。

list()メソッドは

メッセージのリストを要求します。結果は以下のような形式で表されます。 (response, ['mesg_num octets', ...]) which が与えられると、それによりメッセージを指定します。

ということです。

main()の中身(後半)

後半は以下のようになっています。

    if len(l) and l[1]:
        m = s.retr(1)

        msgbody = '\n'.join(m[1])
        add_moblog_entry(msgbody,
         'http://[user]:[pass]@url.of.blog/path2/blog/','password4mail')

        s.dele(1)

    s.quit()

    return

最初に変数lおよびlの1番目の存在を確認し、変数mにretr()メソッドによって得られる3要素のタプルを代入しています。

さらにmsgbodyに「'\n'.join(m[1])」なるものが代入されています。

上述したようにm[1]は「メール本体の内容が1行ごとに分割されて含まれたリスト」になりますが、「'\n'.join(m[1])」という操作の結果はどうなるのでしょうか。

試しに以下のコードを実行してみます。

# 文字列からなるリストを用意
>>> test_m = ['1', '2', '3']

# moblog.pyと同様のことをしてみる
>>> test_msgbody = '\n'.join(test_m)

# 中身はどうなったのぉ~
>>> test_msgbody
'1\n2\n3'

ということは、この操作によってリスト内の各要素である文字列が「\n」でつなげられて、一つの文字列になっているということですね。

ということは、moblog.py内の変数msgbodyには、メール本体の内容が改行記号でつなげられた文字列が入っているわけですね。

この後add_moblog_entry()を使っているわけですが、その内容についてはまた今度見ることにします。

最後にdele()メソッドおよびquit()メソッドを利用して、メール削除フラグを立てて接続を終了しています。削除に関してはカスタマイズする余地というかやりようがありそうです。

カテゴリ
Python Python
moblog moblog
トラックバック用URL:
http://nagosui.org:8080/Nagosui/COREBlog2/fight-for-moblog-2-1/tbping
このBlogについて
Plone, Zope, Pythonなどのトピックについてのメモです。
カテゴリ
Plone (98)
Plone Products (23)
COREBlog2 (31)
COREBlog1 (29)
ReadingCOREBlog (7)
Zope (66)
Turbogears (18)
Django (12)
Python (25)
Linux (30)
Nagosui (12)
Design (33)
Misc (48)
moblog (5)
最近のエントリ
浜松ブラスバンド定期演奏会2008 nyusuke 2008年11月24日
Glossy Horizontal Menuを使う nyusuke 2008年11月17日
第3回Python東海終了 nyusuke 2008年11月17日
Universalじゃない件 nyusuke 2008年11月15日
最近のコメント
Re:WebデザイナーのためのDjangoはじめの一歩 nyusuke 2007年06月01日
Re:WebデザイナーのためのDjangoはじめの一歩 pateo 2007年05月31日
Re:東海Python Workshop 01終了 nyusuke 2007年05月31日
Re:東海Python Workshop 01終了 kfuruhata 2007年05月30日