何ができる?
Gmailに特定のメールが届くとカレンダーに予定が追加されます。
特定のラベルがついたメールを読み込んで、中身をあれやこれやしてカレンダーに追加していきます。
きっかけ
謎解きイベントの予約を頻繁に取っているのですが、カレンダーに予定を入れていくのが面倒になってきたので自動化した次第です。
自動追加 されないかなーと思ったのですがされる対象が限られているんですね。
最初はIFTTTやMS Flowだけでなんとかならないかなーと思ったのですが、なんともならなかったのでGASを書くことにしました。
やったこと
ラベルの設定
GASとは直接関係ありませんが、これが失敗しているとこの後総崩れするので大事です。
今回は特定のメールアドレスから送られてくること、特定のキーワードがタイトルに含まれていることが確定していたので、
from と subject を検索条件で指定してあげるとうまくいきました。
検索条件の例
from:info@event.example.com subject:予約が完了しました
メールの取得
特定のラベルがついたメールを取得するようにします。
// 検索条件。Gmailの検索欄と同じものを指定できる。
var terms = "label:イベント予約 is:unread";
var max = 100;
// スレッド形式で該当するメールを取得する。
var threads = GmailApp.search(terms, 0, max);
取得されるメールはスレッド形式となっています。1時間以内くらいで複数回予約をとるとスレッドにまとめられるようです。どういう条件なのか知りたい。
カレンダーへの追加
カレンダーオブジェクトを取得し、所定の形式に加工してイベントを登録します。加工部分は後述します。
それ以外にも、ラベル付けや既読状態をフラグとして使っています。
// 前項で取得したメール
var threads = getThreads();
var calendar = CalendarApp.getCalendarById("calendarid@group.calendar.google.com");
for(var j in threads){
for (var k in threads[j]) {
var message = threads[j][k];
// 既読を処理済み扱いしてスキップするときはこうする
if(!message.isUnread()) continue;
try {
var result = // ここで加工する
// タイトルと開始・終了時刻までは必須。
var event = calendar.createEvent(result.title, result.starts, result.ends, result.metadata);
Logger.log("Added: %s %s - %s", result.title, result.starts, result.ends);
}
catch (ex) {
Logger.log(ex);
var failed = GmailApp.getUserLabelByName("Failed");
// 登録失敗のラベルをつける
message.getThread().addLabel(failed);
continue;
} finally {
// 既読にして処理済みとする
message.markRead();
}
}
}
本文やタイトルから予定に必要な情報を取得する
タイトルと本文を取得したあとは正規表現チェッカー で頑張ります。
// タイトルと本文を取得する
var subject = message.getSubject();
var body = message.getBody();
// あとは正規表現で頑張る。
var order = body.match(/---------------お申込情報--------------([\s\S]+)決済方法/)[1];
var location = order.match(/会場 ?:[\s]+(.+)/)[1];
var title = order.match(/公演名 :[\s]+(.+)/)[1];
var date = order.match(/([0-9]+年[0-9]+月[0-9]+)日\([月火水木金土日]\)/)[1].replace(/[年月]/g, "/");
var time = order.match(/[0-9]+:[0-9]+/g);
var starts = new Date(date + " " + time[0]);
var ends = new Date(date + " " + time[0]);
ends.setHours(ends.getHours() + 2);
var result = { title: title, starts: starts, ends: ends, metadata: { location: location } };
トリガーの構成
実行する関数を決めて、トリガーを設定します。今回は処理時間がシビアではないもののできればすぐ確認したいので、実行間隔5分おきとしています。
その後
実行してみると無事登録できました。ただ、たまに書式が変わるので登録に失敗することがあるので、定期的にメンテナンスが必要ですね。。。。