メールからはてなグラフを更新するサンプル (さくらインターネット)

街に溢れている新入社員っぽい人たちがなんとなくまぶしくて、思わず目を細めてしまうbonlifeです。細めなくても細いんですけどね。
さてさて。モブログ的なノリでメール受信をトリガーに処理をさせるスクリプトを試してみたいなぁ、ということでこの間作ったはてなグラフ数値登録APIを使うスクリプトを応用して稚拙なサンプルを書いてみました。
まず、さくらインターネットを使っているので、コントロールパネルからメールアドレスを作成。メールの場合、「スケーラブルWebサイト」の6章(電子メールの章)にも載っているように、To:のアドレスで処理を分けるぐらいしか現時点では良い方法がありませんので、推測されにくい長い複雑なメールアドレスを作成。"/home/ユーザID/MailBox/メールアドレス"というディレクトリが作成されているので、そこにTelneでアクセスするなりして、.mailfilter というファイルを作ります。内容は以下のような感じです。

to "| /usr/local/bin/python /home/ユーザID/scripts/mail2hategra.py >> /home/ユーザID/scripts/log/mail2hategra.log"

追記モードのリダイレクトでログを残すようにしていますが、このディレクトリがないとエラーになってしまうので、事前に作成しておきます。また、開発中など、メールも一応残しておきたい場合には、先頭の to を cc に変更しておきます。で、前回作った以下の2ファイルをそのまま流用します。パスが通ったディレクトリに置くか、今回作成したスクリプトと同じディレクトリに置きます。

  • AtomClient.py
  • HateGra.py

[参考]

いよいよ、メールを受け取ってその内容を分解し、はてなグラフに登録するスクリプトです。

  • mail2hategra.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import re
import datetime
import codecs
from email import *

from HateGra import HateGra

sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

def email_body_get(file):
    msg = message_from_file(file)
    charset = msg.get_charset()
    body = msg.get_payload(decode=1)
    charset = msg.get_content_charset()
    return unicode(body, charset)

def text_to_list(text):
    lines = [line.split(' ') for line in text.split('\n') if len(line.split(' ')) == 2] 
    return lines

def value_check(value):
    digit_for_graph = re.compile(r'[0-9]+(\.[0-9]{0,2})?')
    return digit_for_graph.match(value)

def log_print(result):
    if result['response']['status'] == 201:
        print result['time'], result['setting']
    else:
        print result['time'], result['setting'], result['response']

hg = HateGra()
hg.credentials('graph.hatena.ne.jp', 'username', 'password')

lines = text_to_list(email_body_get(sys.stdin))
[log_print(hg.register_value(line[0].encode('utf8'),line[1].encode('utf8'))) for line in lines if value_check(line[1])] 

モジュールのimportの仕方に統一感がない、などやっつけ仕事丸出しな感じですが、ご愛嬌。簡単に説明すると、以下のような流れで処理しています。

ということなので、メール本文の書式は以下のようになります。(Subjectは全くチェックしてません。)

体重 69.0
体脂肪率 15.5

試してみたところ、ケータイメール(iモード)、Gmailの両方からはてなグラフの更新に成功!小さいスクリプトでも結果が出ると気持ち良いですね。それにしても、このスクリプト文字コードUTF-8エンコードするのはなんとなく気持ち悪いですね。Unicode文字列を渡して、はてなグラフ用のクラスの方でエンコードする方がキレイかもしれないです。
今後のToDoです。

  • メールのヘッダ部のFrom(など)をチェックし、妥当なメールか確認する
  • 日付も指定できるようにする
  • (複数の記述方式に対応する)

日付の指定機能を追加するのは難しくなさそうですが、これをやってしまうと誰かにはてなグラフ更新用のメールアドレスを知られてしまった場合、過去にさかのぼって値を上書きされてしまう危険がありますね…。とか細かいことを気にする前に、文字コードの変換まわりをちゃんと整理したいところです。なんだか難しいんですよね。PC上では上手く行くスクリプトがサーバ上ではエラーになったり。おそらく、デフォルトエンコーディングあたりに原因があるんだと思いますが、ちゃんと(勉強|調査)できてません。
こんな感じでちまちまとPython勉強していきまーす。