Symfoware

Symfowareについての考察blog

PythonでGmailに送信されたメールの内容と添付ファイルを取得する

Pythonでメールの受信方法がよくわからず苦戦したのでメモしておきます。



gmailでの設定



IMAP4での接続を許可します。
おそらく、デフォルトで許可になっていると思いますが、確認方法は画面右上の設定ボタンから[設定]を選択。
36_001.png


[メール転送とPOP/IMAP]タブを選択し、IMAPアクセスのステータスが[IMAP有効]になっていればOKです。
36_002.png


また、事前にこんな画像の添付付きのメールを送っておきました。
36_003.png





サンプルプログラム



メールサーバーは「imap.gmail.com」
ユーザー名は使用しているgmailのアドレス。
パスワードはそのメールアドレスを閲覧するときのものを指定します。

また、添付ファイルは一旦cStringIOのオブジェクトに突っ込んでおくことにしました。
解析時に必要であればファイルに出力して確認します。


  1. # -*- coding:utf-8 -*-
  2. import imaplib,email,email.Header
  3. import time
  4. import cStringIO
  5. class imap4mail(object):
  6.     
  7.     def __init__(self, data):
  8.         """
  9.         コンストラクタで与えられたメールデータの解析を実行する
  10.         """
  11.         self.files = {}
  12.         
  13.         #メッセージをパース
  14.         msg = email.message_from_string(data)
  15.         #タイトル取得
  16.         self.title = self.decode(msg.get('Subject'))
  17.         #送信者取得
  18.         self.sender = self.decode(msg.get('From'))
  19.         #送信日付取得
  20.         self.date = self.get_format_date(msg.get('Date'))
  21.         
  22.         #添付ファイルを抽出
  23.         for part in msg.walk():
  24.             if part.get_content_maintype() == 'multipart':
  25.                 continue
  26.                 
  27.             #ファイル名を取得
  28.             filename = part.get_filename()
  29.             
  30.             #ファイル名が取得できなければ本文
  31.             if not filename:
  32.                 self.body = self.decode_body(part)
  33.                 
  34.             #ファイル名が存在すれば添付ファイル
  35.             else:
  36.                 tmpfile = cStringIO.StringIO()
  37.                 tmpfile.write(part.get_payload(decode=1))
  38.                 
  39.                 self.files[filename] = tmpfile
  40.     def decode(self, dec_target):
  41.         """
  42.         メールタイトル、送信者のデコード
  43.         """
  44.         decodefrag = email.Header.decode_header(dec_target)
  45.         title = ''
  46.         
  47.         for frag, enc in decodefrag:
  48.             if enc:
  49.                 title += unicode(frag, enc)
  50.             else:
  51.                 title += unicode(frag)
  52.         
  53.         return title
  54.         
  55.     
  56.     def decode_body(self, part):
  57.         """
  58.         メール本文のデコード
  59.         """
  60.         body = ''
  61.         charset = str(part.get_content_charset())
  62.         
  63.         if charset:
  64.             body = unicode(part.get_payload(), charset)
  65.             
  66.         else:
  67.             body = part.get_payload()
  68.             
  69.         return body
  70.     def get_format_date(self, date_string):
  71.         """
  72.         メールの日付をtimeに変換
  73.         http://www.faqs.org/rfcs/rfc2822.html
  74.         "Jan" / "Feb" / "Mar" / "Apr" /"May" / "Jun" / "Jul" / "Aug" /"Sep" / "Oct" / "Nov" / "Dec"
  75.         Wed, 12 Dec 2007 19:18:10 +0900
  76.         """
  77.         
  78.         format_pattern = '%a, %d %b %Y %H:%M:%S'
  79.         
  80.         #3 Jan 2012 17:58:09という形式でくるパターンもあるので、
  81.         #先頭が数値だったらパターンを変更
  82.         if date_string[0].isdigit():
  83.             format_pattern = '%d %b %Y %H:%M:%S'
  84.         
  85.         return time.strptime(date_string[0:-6], format_pattern)
  86. def analize_mail(mail):
  87.     
  88.     #取得したメールの内容を表示
  89.     print( mail.sender )
  90.     print( mail.date )
  91.     print( mail.title )
  92.     print( mail.body)
  93.     
  94.     for key, value in mail.files.items():
  95.         print key
  96.         with open(key, 'w') as f:
  97.             f.write(value.getvalue())
  98. if __name__ == "__main__":
  99.     
  100.     host = 'imap.gmail.com'
  101.     user = 'example@gmail.com'
  102.     password = 'password'
  103.     mailbox = 'INBOX'
  104.     
  105.     #メールサーバ指定
  106.     M = imaplib.IMAP4_SSL(host=host)
  107.     #ログイン
  108.     M.login(user, password)
  109.     
  110.     #メールボックス選択
  111.     M.select(mailbox)
  112.     
  113.     typ, data = M.search(None, 'ALL')
  114.     for num in data[0].split():
  115.         typ, data = M.fetch(num, '(RFC822)')
  116.         mail = imap4mail(data[0][1])
  117.         analize_mail(mail)
  118.         
  119.     M.close()
  120.     M.logout()





実行してみると、非常に素っ気無いですがメールの内容が確かに解析できてます。
スクリプトを実行した階層に「image.jpg」という名前で添付ファイルが
取得できているはずです。

送信者の名前 <sample@mail.example.com>
time.struct_time(tm_year=2012, tm_mon=1, tm_mday=3, tm_hour=17, tm_min=58, tm_sec=9, tm_wday=1, tm_yday=3, tm_isdst=-1)
メールの件名
メールの本文

image.jpg




機種依存文字や、送信元のメーラーによるデータの差異が怖いところですが、
とりあえずメールの受信が行えました。





【参考URL】
0.10. imaplib ― IMAP4 プロトコルクライアント
http://www.python.jp/doc/release/library/imaplib.html

15.3. time ― 時刻データへのアクセスと変換
http://www.python.jp/doc/release/library/time.html



関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2012/01/03(火) 19:36:12|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Python Gmailに届いたメールの内容をmantisに自動で転記する | ホーム | Python SOAP通信でmantisに案件を追加する(suds使用)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
https://symfoware.blog.fc2.com/tb.php/891-accf0284
この記事にトラックバックする(FC2ブログユーザー)