📅

どんな予約完了メールでも自動でGoogleカレンダーへ登録する方法

2023/08/31に公開

はじめに

こんにちは。株式会社TERASSでコーポレートエンジニアをしているHayashiです。

Gmailに届いた予約完了メールを自動でGoogleカレンダーに登録できたら楽ですよね?
しかし標準機能だけだと上手く連携ができない・・そんな時のお話です。

標準機能で実現出来ないの?

実は下記のような予約メールは、標準で自動連携できるようになっています。

・フライト、列車、バスの予約
・ホテルやレストランの予約
・映画やコンサートなど、チケットが必要なイベント

しかし弊社は下記のような要件でして、標準機能では実現不可でした。

  • オフィスにゲストが来る際に、外部サイトを通じて来訪予約いただいている。
  • 予約メールは届くが、Googleカレンダーで確認できるようにしたい。

登録までの流れ

  1. Gmailに予約完了メールが届く
  2. Zapierを通して、Google Apps Scriptを呼び出す
  3. Googleカレンダーに予定が登録される

1.予約完了メールが届く

下記のようなメールが届くとします。

件名: 来訪登録のご案内
▼本文

○○オフィスへの来訪登録が完了しました。
<登録内容の詳細>
入館予約番号: A12345
ご来訪者: 株式会社○○ 山田 太郎 様
ご来訪日時:2023/09/01 14:30

2.Zapierを通して、Google Apps Scriptを呼び出す

さて、メールを受信したタイミングで、カレンダー登録処理を実行させる必要がありますが...
ここで使うのがZapierという自動化ツールです。

Zapierでは一つの自動化ワークフローを作るにあたり、TriggerとActionを定義します。

  • Trigger:何をきっかけとして処理を開始するか
  • Action:何をするか

ここでは下記のように定義します。

  • Trigger:件名が「○○オフィスへの来訪登録が完了しました。」というメールが届いたら
  • Action:Webhookであらかじめ作成したGASアプリケーションを実行する

3. Googleカレンダーに予定が登録される

GASアプリケーションの中でカレンダーの登録処理が走るわけですが、
参考までにGASの中身を紹介します。

カレンダー登録処理

今回、カレンダー登録を終えた予約完了メールは既読としてマークします。
そのためまず対象メールを「特定の件名」「未読」で絞り込みます。

const threads = GmailApp.search('{subject:○○オフィスへの来訪登録が完了しました。} is:unread');

しかしここで厄介なのが、Gmailはスレッドという仕組みを採用していることです。
一つのスレッドの中に、複数件のメッセージ(メール)が格納されています。
参考:https://blog.synnex.co.jp/google/gmail-gas/

上記のGmailApp.search()ではスレッドの配列が返却されるので、for文を使って各スレッドからメッセージを順に取り出して、カレンダーへ登録していきます。

const props = PropertiesService.getScriptProperties().getProperties();
const calendarID = props.calendarID;
const calendar = CalendarApp.getCalendarById(calendarID);

for (let i = 0; i < threads.length; i++) {
    const messages = threads[i].getMessages();
    for (let j = 0; j < messages.length; j++) {
      const message = messages[j];

      if (message.isUnread()) {
	  const body = message.getPlainBody();

	    // メール本文からゲスト情報を取得する
	  const name = body.match(/ご来訪者:(.*)/)[0].slice(5).trim();
	  const date = body.match(/ご来訪日時:(.*)/)[0].slice(6).trim();
	  const reservationNum = body.match(/入館予約番号:(.*)/)[0].slice(7).trim();
	  
	  // 予定登録に必要な情報を作成する
	  const title = `${name}_${reservationNum}`;
	  const startTime = new Date(date);
	  let endTime = new Date(date);
	  endTime.setHours(endTime.getHours() + 1);

	  // カレンダーに予定を追加
	  calendar.createEvent(title, startTime , endTime);

	  // 既読としてマーク
	  message.markRead();
	} 
    }
  }   

Zapierから呼び出せるように

ZapierからのPOSTを受け取るため、doPost()を定義します。

function doPost(e) {
  let jsonString = e.postData.getDataAsString();
  let data = JSON.parse(jsonString);
  (省略)
  addEventFromEmail(); //カレンダー登録処理
  return ContentService.createTextOutput('Success');
}

また最後に、Webアプリケーションとして公開します。
参考:https://auto-worker.com/blog/?p=3565

無事処理が成功すると

指定したGoogleカレンダーに予定が登録されます。

最後に

今回は処理のトリガーとしてZapierを利用しましたが、GAS単体で5~10分刻みで定期実行しても良いと思います。

またカレンダーの予定タイトルを「ゲスト名_予約番号」のようにすることで、予約変更メールや予約キャンセルメールにも対応できます。

例えば

  1. 「ゲスト名_予約番号」でGoogleカレンダー内を検索
  2. ヒットした予定を削除する
  3. (予約変更の場合) 新規日程で再登録する

気になった方はぜひ試してみてください。

Terass Tech Blog

Discussion