techman999の日記

とある大学の教員の日々の備忘録

iCalのデータを読み込んで、メールで送信

iCalのicsファイルから今日の予定を読み込んで、メールで送信するPythonプログラムを書いてみた。

  1. icsファイルの取り扱い

Pythonで、icsファイルを取り扱うのに適したモジュールはないかと調べていたら、あった。

iCalendar package for Python, http://codespeak.net/icalendar/

安定版のリリースが、2006年?と思ったが、以下のようにSVNで開発版のソースを取得したらicalendar 2.2が取得できた。
You can also check out the development version of iCalendar from subversion, using a command like:
svn co http://codespeak.net/svn/iCalendar/trunk iCalendar

よく調べたら、pypiに登録されていた。http://pypi.python.org/pypi/icalendar/
こっちだと、githubソースコードがあった。http://github.com/collective/icalendar

Python2.7で、icalendar 3.0を使ってみたが、最終的に動作させる環境がFreeBSDなので、
portsにicalendarのパッケージがあったが、バージョンが2.1だったので
ひとまず、バージョン2.2でプログラムを組むことにした。

icsファイルに記述されたデータを表示する例。

from icalendar import Calendar
from date time import datetime

cal = Calendar.from_string(open('schedule.ics', rb').read())
body = ""
for ev in cal.walk():
    if ev.name == 'VEVENT':
        start_dt = ev.decoded("dtstart")
        end_dt = ev.decoded("dtend")
        summary = ev['summary'].encode('utf-8')
        print "{start} - {end} : {summary}".format(start=start_dt.strftime("%Y/%m/%d %H:%M"), end=end_dt.strftime("%Y/%m/%d %H:%M"), summary=summary)
        # body = "{start} - {end} : {summary}".format(start=start_dt.strftime("%Y/%m/%d %H:%M"), end=end_dt.strftime("%Y/%m/%d %H:%M"), summary=summary)
  1. メールで送信

icalendarモジュールで取り出した今日の予定をメールで送信する。

import smtplib
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email.Header import Header

encoding = 'ISO-2022-JP'

msg = MIMEText(body.encode(encoding), 'plain', encoding) 
# bodyはicsファイルから取得したスケジュールの文字列
msg['Subject'] = Header(u'本日の予定', encoding)
msg['From'] = 'Hoge<hoge@example.com>'
msg['To'] = 'dummy@example.com'
msg['Date'] = formatdate()

from_addr = 'huge@example.com'
to_addr = ['dummy@example.com']
send(from_addr, to_addr, msg)

UTF-8で文字列が格納されているbodyを、MIMETextの第一引数として渡すが、
このとき、UTF-8からISO-2022-JPへencodeしてやらないと、
SubjectはISO-2022-JP、本文はUTF-8ととなり、本文だけ文字化けして読めないという悲しい状況に陥る。
(ぐぐって、参考にしたサイトで変更していないものもあった...)

  1. HTTP+Basic認証

icsファイルを、WebDavサーバ上に置いている。
スケジュールなので、一応Basic認証をかけている。
urllib2モジュールで、icsファイルを取得する処理は以下の通り。

import urllib2

passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, 'webserver_no_FQDN', 'username', 'password')
auth_handler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
url = "http://example.com/dav/schedule.ics"
r = urllib2.urlopen(url)
tmp_file = open('/tmp/schedule.ics', 'w')
tmp_file.write(r.read())
tmp_file.close()
  1. UTF-8での文字列処理

スクリプト文字コードUTF-8にしたり、スクリプトの最初に #-*- coding: utf-8 -*-と記述しても、
実行すると、以下のようにUTF-8の処理で引っかかる。

techman999@minako:~/dev/git/pyical$ python today_schedule.py  File "today_schedule.py", line 40
SyntaxError: Non-ASCII character '\xe5' in file today_schedule.py on line 40, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

結論としては、/usr/lib/python2.6/sitecustomize.py を以下のように追記して対処した。

import sys
sys.setdefaultencoding("utf-8")

こんな感じで、トータル4時間で完成。
たまには、お遊びプログラム書いていかないとね:p