trash-area.com ≫ blog ≫ GAEGmailフィードとGmailスクレイピング

2009年06月08日 1

POP3 も IMAPも使えない環境でGMailの本文を受信しようといろいろ試行錯誤した残念な結果です。
やりたかったことは限られた環境内での GMailのメール駆動アプリの開発です。
もちろん メールの .filter もムリな環境です。

そもそもスクレイピングするっていう時点でほぼサーバサイドなわけですが
それでいて POP3 も IMAPも使えないなんて状況あるんでしょうかね。

まー、結論からすると Google App Engine がそうです。はい。

Google App Engine で GMail を受信したらスクリプトを起動させたかったのですが
現時点のわたくしの脳みそではできませんでした。

ちなみに smtp2web という webサービスがありますが
これなら外部のサーバでそのままアプリ作ったほうがいいかなーと。

ということで Google App Engine でメール受信はできなかったのに加えて、
POP3 も IMAP も(.filter も)使えない環境ってのがほかに思い浮かばなかったので
今のとこ、どこにも活用できそうも無いためここに貼り付けます。

Google App Engine でメール受信アプリをしようとしてたため、
サンプルは Google App Engine(Python)のソースになってますが、開発サーバでしか動作しません。

Gmail フィード

いろんなところで言及されてますが、
https://mail.google.com/mail/feed/atom/label/
で、特定のラベルの未読メールを atom で取得できます。(これ以外にもいっぱいあります)

なので、こいつを cron で叩いて擬似的なメール駆動のトリガーに。

username = 'hoge'       # hoge@gmail.comなら
password = 'xxxxxx'
label    = 'Ameba'
 
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
headers = {'Authorization': "Basic %s" % base64string}
 
url = 'https://mail.google.com/mail/feed/atom/%s' % label
result = urlfetch.fetch(url, '', urlfetch.GET, headers)
 
dom = fromstring(result.content)
 
namespace ='http://purl.org/atom/ns#'
items = dom.findall('.//{%s}entry' % namespace)
 
for item in items:
    l = item.find('./{%s}link' % namespace)
 
    m = re.search('message_id=(.*?)&', l.get('href'))
    thid = m.group(1)     # スレッドID(?)

Basic 認証で叩きます。
link要素の href属性に本文へのアドレスが入ってるのでそこからスレッドID(?)を抜き出してます。
ここでは省略してますが、タイトルやらいろいろ取れます。

Gmail スクレイピング

上で取得したスレッドIDから Gmailをスクレイピングするんですけど
まともにやると結構難儀そうなのと、「メールのソースを取得したかった」ので
ここのリンクを生成することにします。

gmail

パラメータ「ik=14f89f4596」の意味がわからなかったんですけど、たぶん「メールのソース」なんだと思います。環境によって違うのならご一方下さい。

    url_0 = 'https://mail.google.com/mail/'
    url_1 = 'https://www.google.com/accounts/ServiceLoginBoxAuth'
    url_2 = 'https://www.google.com/accounts/CheckCookie?chtml=LoginDoneHtml'
    url_3 = 'https://mail.google.com/mail/h/'
    url_4 = 'https://mail.google.com/mail/?ui=&ik=14f89f4596&view=om&th=%s'
 
    login_params = {'continue': url_0,
                    'Email': 'hoge@gmail.com',
                    'Passwd': 'xxxxxx',
                    }
    params = urllib.urlencode(login_params)
 
    headers = {}
    result = urlfetch.fetch(url_1, params, urlfetch.POST, headers, True)
 
    ck = Cookie.SimpleCookie()
    ck.load(result.headers['set-cookie'])
 
    s = ''
    s += ck['GAUSR'].output(attrs=[], header='') + ','
    s += ck['LSID'].output(attrs=[], header='')  + ','
    s += ck['SID'].output(attrs=[], header='') + ','
 
    headers = {'Cookie': s}
    result = urlfetch.fetch(url=url_2, method=urlfetch.POST, headers=headers)
 
    result = urlfetch.fetch(url=url_3, method=urlfetch.GET, headers=headers, follow_redirects=True)
 
    ck.load(result.headers['set-cookie'])
 
    s = ''
    s += ck['GMAIL_AT'].output(attrs=[], header='') + ','
    s += ck['GX'].output(attrs=[], header='')  + ','
    s += ck['S'].output(attrs=[], header='') + ','
 
    headers = {'Cookie': s}
    result = urlfetch.fetch(url=url_4 % thid, method=urlfetch.GET, headers=headers, follow_redirects=True)
 
    print result.content

1. https://www.google.com/accounts/ServiceLoginBoxAuth を POST で叩きます。
2. Cookie が返ってくるので必要なやつをくっつけて https://www.google.com/accounts/CheckCookie?chtml=LoginDoneHtml に POST。
3. https://mail.google.com/mail/h/ に GET。これは携帯用のGMailアドレスです。1. で指定した continue パラメータの値(PC用)と違いますが、GAEでPC用だとリダイレクトの数が多すぎてエラーになったからです。GAE でなければ素直に PC用のを指定しても問題ないかと思います。
4. 今度はGmail用のCookieが返ってくるので、それをくっつけて https://mail.google.com/mail/?ui=&ik=14f89f4596&view=om&th={スレッドID} を呼ぶとメールのソースが取得できます。

本番サーバで動かなかったのでメール本文のデコード処理等はくっつけてません。
リクエストヘッダをいろいろいじったのですけど、開発サーバと本番サーバの違いは keep-alive くらいしかありませんでした。

GAE でうまく動いた方がいらっしゃれば教えてください。

ちなみに CookieJar が使える環境ならもうちょっとシンプルです。
もちろんGAEでは使えません。

    cj = CookieJar()
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
    opener.addheaders = headers
    result = opener.open(url_1, params)
    result = opener.open(url_2)
    result = opener.open(url_0)
    result = opener.open(url_4 % thid)
    print( result.read() )
ソーシャルブックマーク
はてな Livedoor del.icio.us
関連してそうな記事
同じカテゴリーの別の記事
タグ
, , , ,
トラックバックURL
  1. […] 参考: GmailフィードとGmailスクレイピング | trash-area.com […]

コメント
1件のコメント

Comment RSS

コメントをどうぞ

*反映されるまでに時間がかかることがあります。
*メールアドレスはアバターの使用に使います。