Gmailに受信した予約完了メールからGoogle Calendarにイベント追加するGASスクリプト


# 経緯
Skype英会話の予約完了メールから、Google Calendarに追加するスクリプトを書いて、去年くらいから使っています。
そこのメールがちょいちょいフォーマットが変わったりするのと新たにフィットネスにも通い始めてそっちの予約メールにも対応したかったので少し書き直してみました。


# 参考にした記事
[【GAS】DMM英会話の予約完了メールから自動的にカレンダーイベントを作成するスクリプト](http://koucs.com/articles/13)

この方は全メールから、対象のメールを検索されるスクリプトを書いてましたが、自分の環境ではメール数が多すぎるせいか、うまく回らなかったのでGmailのラベルを検索用+処理済みフラグに使うようにしてみました。


# 事前準備

* Google Calendarでイベント追加用のカレンダー作成 → [参考](https://support.google.com/calendar/answer/37095?hl=ja)
* Gmailで予約メールに一時的につけるラベルと自動化を設定 → [参考](http://www.appsupport.jp/gmail/filters/)


# 使い方
* Google Driveを開き新規のGoogle Apps Scriptを作成

![image](https://qiita-image-store.s3.amazonaws.com/0/13161/4de2e82f-0950-a09e-53c6-9779f4880844.png)

* 以下のコードを貼り付けて実行

## コード
``` calendar.gs
/*
 * Gmailに受信した予約完了メールから自動的にGoogle Calendarにイベント登録する
 * サービス/会社ごとに微妙に日時・タイトルフォーマットが違うので設定できるようにしてみた
*/


// 日時の正規表現パターン
var RegExpPattern = {
  1: { // 例: FeelCycleの予約完了メールパターン
    regExp_date: /(\d{4}年\d{1,2}月\d{1,2}日)/gm,// 日時形式(ex: 2016年6月25日)
    regExp_time: /(\d{2}:\d{2})/gm,// 時刻書式(ex: 20:15)
    regExp_replace: /[年月日]/gm, // 日時に含まれる、「年,月,日」を「/」に置換する
    regExp_pos: 0 // 本文中何回目に出てくる日時・時刻を開始日・時刻とするか(通常は0=1回目)
  },
  2: { // 例: QQ Englisの予約完了メールパターン
    regExp_date: /(\d{4}-\d{2}-\d{2})/gm,// 日時形式(ex: 2016-06-25)
    regExp_time: /(\d{2}:\d{2})/gm, // 時刻書式(ex: 20:15)
    regExp_replace: /-/gm, // 日時に含まれる、「-」を「/」に置換する
    regExp_pos: 1 // 以下の文例のように、受付日時が最初に来るので1(2回目)を指定
  }
}


// QQ Englishのメール文例
// 日頃はQQイングリッシュをご利用頂き、ありがとうございます。
// 下記の内容でご予約を受け付けました。内容をご確認下さい。
// 
// 【ご予約内容】受付日時： 2016-07-28 15:56
// ------------------------------------------------
// 日付： 2016-08-06
// 時間： 07:30-08:00
// 教師： Saravi
// カリキュラム： ビジネスイングリッシュ
// ------------------------------------------------



function main(){
  createEventFromGmail("QQENG","English", "レッスン予約完了", 2,30)  
  // イベント名: QQENG
  // カレンダー名:English
  // タイトルに含まれるキーワード: 予約
  // 日時の正規表現パターン: 1
  // 一回あたりのレッスン時間: 30分
  createEventFromGmail("FeelCycle","Excercise", "予約", 1,45)
  // イベント名: FeelCycle
  // カレンダー名:Excercise
  // タイトルに含まれるキーワード: 予約
  // 日時の正規表現パターン: 2  
  // 一回あたりのレッスン時間: 45分  
}


function createEventFromGmail (EventName, CalendarName, Keyword,RegExpPatternNo,DurationMin) {
  
 // EventNameのラベルがついているメールスレッドを取り出す 
 var threads = GmailApp.getUserLabelByName(EventName).getThreads();

// それぞれのスレッドに関して
 for (var i = 0,thread; i<threads.length; i++) { 
   thread = threads[i]        
   
   // 含まれるメッセージを取り出し、
   var messages = thread.getMessages();
   for(var j = 0,message; j<messages.length; j++){
     var message = messages[j]
     // メッセージのタイトルにKeywordが含まれていた場合は
     if(message.getSubject().indexOf(Keyword)>0){
       
       // 本文を取り出して、
       var body = message.getBody();      
       
       // 設定したパターンにマッチする日時を探して、
       var regExp_date = RegExpPattern[RegExpPatternNo].regExp_date;
       var regExp_time = RegExpPattern[RegExpPatternNo].regExp_time;
       var regExp_replace = RegExpPattern[RegExpPatternNo].regExp_replace;
       var regExp_pos = RegExpPattern[RegExpPatternNo].regExp_pos;       
       
       var date = body.match(regExp_date);
       var time = body.match(regExp_time); 
       
       // イベント開始時刻
       var from = new Date(date[regExp_pos].replace(regExp_replace,'/')+" "+time[regExp_pos])        
       // イベント終了時刻 = 開始時刻 + レッスン時間
       var to = new Date(+from + DurationMin*60*1000);
        
       
       
       // 追加したいCalendarNameという名前のカレンダーを取得し、
       var myCalendar = CalendarApp.getCalendarsByName(CalendarName)[0];       
       
       // ちゃんと存在したら
        if(myCalendar){
          // 同じ時刻に、同じイベント名で登録されているイベントを探してみて、
          var existingEvents = myCalendar.getEvents(from, to, {search: EventName})
          // なかったらイベントを作成する
          if(existingEvents.length == 0){            
            myCalendar.createEvent(EventName, from,to, {description: body});            
          } else {
            Logger.log(from)
            Logger.log("イベント登録済みです");
          }
        }else{       
          Logger.log("カレンダーが見つかりませんでした: "+CalendarName);
        }
    }
  }
  // 繰り返し処理がされないためにラベルを削除
  thread.removeLabel(GmailApp.getUserLabelByName(EventName)); 
 }
}



```