【Google Apps Script (GAS)】イベントのリマインドメールを自動送信する

2020年1月26日Google Apps

イベントを企画し、開催日の1週間前のタイミングで参加者に対しリマインドメールを送る。
実業務でもありそうな処理をGoogle Apps Scriptで自動化してみようと思います。

自動化にあたって、作成するGoogleフォームのタイトル(ファイル名)とカレンダーに登録するイベント名が同一でなければ動きません。

募集フォームを作成する

スポンサーリンク

Googleフォームを使って募集フォームを作成します。
「+ 新規」→「その他」からGoogleフォームを起動して、募集の必要項目を設定します。

募集フォーム完成例

募集フォームの作成にあたって
1項目目に「メールアドレス」、
2項目目に「氏名」を入力するように設定します。

作成した募集フォームにThankYouメールを返信するようにするにはこちらを参照してください。

カレンダーにイベントを登録する

Googleカレンダーにイベントを登録します。スクリプトから参照できるようにするため、同一のアカウントのカレンダーに登録します。
募集フォームのタイトルと同一のイベント名で登録します。

登録の手順は割愛します。

リマインドメール送信プログラムを作成する

スポンサーリンク

プログラムコード

Googleドライブの「+ 新規」→「その他」からGoogle Apps Scriptを選択します。リマインドメール送信バッチは1日1回、指定時間に実行するようにするためスタンドアロンScriptで作成します。

/**
 * リマインドメール送信バッチ
 * カレンダーからイベントを取得し、対応する応募フォームを特定する
 * 応募フォームに応募した応募者にリマインドメールを送信する
 * @return なし
 */
function remindMailBatch() {
  console.info('remindMailBatch Start');
  
  var userProperties = PropertiesService.getScriptProperties();
  
  // 現在日付、未来日付を取得する
  var futurDate = new Date();
  var laterDate = userProperties.getProperty('laterDate');
  futurDate.setDate(futurDate.getDate() + parseInt(laterDate, 10));
  
  // カレンダーのイベントを取得する
  var events = CalendarApp.getDefaultCalendar().getEventsForDay(futurDate);
  
  for (var eventIndex = 0; eventIndex < events.length; eventIndex++) {
    // カレンダーのイベント名と同名のファイル名を持つGoogleFormを検索する
    var files = DriveApp.searchFiles('title = "' + events[eventIndex].getTitle() + '" and mimeType = "' + MimeType.GOOGLE_FORMS + '"');
    
    if (files.hasNext()) {
      var file = files.next();
      
      // ファイルのIDからフォームを取得する
      var form = FormApp.openById(file.getId());
      
      // フォームに紐づくスプレッドシートを取得する
      var spreadSheet = SpreadsheetApp.openById(form.getDestinationId());
      var sheet = spreadSheet.getSheetByName('フォームの回答 1');
      
      var remindMailTemplateId = userProperties.getProperty('remindMailTemplate');
      var remindMailTemplate = DocumentApp.openById(remindMailTemplateId).getBody().getText();
      remindMailTemplate = replaceAll(remindMailTemplate, '{イベント名}', events[eventIndex].getTitle());
      remindMailTemplate = replaceAll(remindMailTemplate, '{lastDate}', laterDate);
      
      for (var row = 2; row <= sheet.getLastRow(); row++) {
        // メールアドレスカラムのデータを取得する
        var mailAddress = sheet.getRange(row, 2).getValue();
        var userName = sheet.getRange(row, 3).getValue();
        if (mailAddress != "") {
          remindMailTemplate = replaceAll(remindMailTemplate, '{氏名}', userName);
          // イベント当日1週間前の場合、リマインドメールを送信する
          GmailApp.sendEmail(mailAddress, events[eventIndex].getTitle() + 'からのお知らせ', remindMailTemplate);
        }
      }
    }
  }
  console.info('remindMailBatch End');
}

メールのテンプレートを置換するためにjavaで言うreplaceAll()を使いたいところですが、JavaScriptにはreplaceAll()メソッドがないため、自作します。

こちらのサイトで紹介されているreplaceAll()のfunction版をサイトのタイトル通りコピペで使わせていただきましたm(_ _)m
https://javascript.programmer-reference.com/js-function-replaceall/

/**
 * 置換処理
 * @return 置換後の文字列
 */
function replaceAll(str, beforeStr, afterStr){
  var reg = new RegExp(beforeStr, "g");
  return str.replace(reg, afterStr);
}

メールテンプレート

リマインドメールに使用するメールテンプレートをGoogleドキュメントで用意します。

{氏名}様

{イベント名}へのご参加ありがとうございます。

{イベント名}開催日の{lastDate}日前となりました。
お会いできることを心よりお待ちしております。

/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_
/_
/_  GAS勉強会事務局
/_
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_

プロパティを設定する

スクリプトエディタの「ファイル」→「プロジェクトのプロパティ」を選択し、開いたウィンドウでスクリプトプロパティタブを開き、プロパティを設定します。

プロパティ名設定値説明
remindMailTemplateGoogleドキュメントのIDリマインドメールのテンプレートを書いたGoogleドキュメントのIDを記載します。
laterDate7リマインドメールを送るイベントの日付が何日後なのかを設定します。
例えば、リマインドメールを1週間前に送りたい場合、「7」を設定します。

トリガーを設定する

最後に「トリガー」を設定します。

トリガーボタンを押下して、設定画面を開きます。
設定は下記の通りです。

実行する関数を選択:remindMailBatch
イベントのソースを選択:時間主導型
時間ベースのトリガーのタイプを選択:日付ベースのタイマー
時刻を選択:午後12時〜1時(こちらの項目は好きな時間を設定してください)

設定したら「保存」ボタンを押下して設定操作が完了します。

ソースコードの解説

スポンサーリンク

少しソースコードの解説をします。

Apps Script ダッシュボードにログを記録する

1行目でスタートログを、再就業でエンドログをconsoleに出力します。必要な時にログを確認するためにLogger.log()ではなくconsoleに出力することで、次に実行されてもログが上書きされることなく残ります。

毎日の動作確認など必要なログを処理の途中に挿入してください。

console.info('remindMailBatch Start');
    :
console.info('remindMailBatch End');

Google Apps Scriptのログ出力についてはこちらを参考にしてください。

カレンダーのイベントを取得し、取得したイベント分だけ、繰り返す

イベントを取得するにはCalendarAppを使います。
カレンダーを取得(getDefaultCalendar())を実行し、getEventsForDay()に未来日を指定してイベントを取得します。

// カレンダーのイベントを取得する
var events = CalendarApp.getDefaultCalendar().getEventsForDay(futurDate);
  
for (var eventIndex = 0; eventIndex < events.length; eventIndex++) {
    :
}

イベント名を使ってGoogleフォームを検索し、参加者に一人ひとりメールを送る

DriveAppのsearchFiles()を使ってGoogleフォームを検索します。

取得したGoogleフォームから回答を保存しているスプレッドシートを取得し、スプレッドシートに記録されているデータを使って、参加者にメールを送信します。

// カレンダーのイベント名と同名のファイル名を持つGoogleFormを検索する
var files = DriveApp.searchFiles('title = "' + events[eventIndex].getTitle() + '" and mimeType = "' + MimeType.GOOGLE_FORMS + '"');
    
if (files.hasNext()) {
  var file = files.next();
      
  // ファイルのIDからフォームを取得する
  var form = FormApp.openById(file.getId());
  // フォームに紐づくスプレッドシートを取得する
  var spreadSheet = SpreadsheetApp.openById(form.getDestinationId());
  var sheet = spreadSheet.getSheetByName('フォームの回答 1');
    :
  for (var row = 2; row <= sheet.getLastRow(); row++) {
      :
    GmailApp.sendEmail(mailAddress, events[eventIndex].getTitle() + 'からのお知らせ', remindMailTemplate);
  }

プロパティから値を取得する

PropertiesServiceのgetScriptPropertiesでスクリプトプロパティを取得します。
getProperty(プロパティ名)で値を取得できます。

var userProperties = PropertiesService.getScriptProperties();
    :
var remindMailTemplateId = userProperties.getProperty('remindMailTemplate');