トリガーで定期的にメールを送信するGAS
スプレッドシート上で一覧になっているメールアドレスへ、トリガーで定期的にメールを送信するGoogleAppsScriptを紹介します。
概要
スプレッドシート(Googleスプレッドシート)上にあるメールアドレス一覧へ、トリガーを用いて定期的にメールを送信するGoogleAppsScriptを作成します。
メール送信の部分については前回までのメール送信GASを利用します。
また、トリガーの詳細についてはこちらを参照ください。
今回は下記3つのタイミングを例にトリガーの使い方を紹介していきます。
- 「スプレッドシートから(起動時)」を用いた不定期送信
- 「時間主導型」を用いた定期送信
- 「時間主導型」を用いて条件ありの定期送信
1. 「スプレッドシートから(起動時)」を用いた不定期送信
ここではGoogleスプレッドシートに紐づいたGASのトリガーのソース「スプレッドシートから」の「起動時」を用います。
このトリガーでは、そのスプレッドシートが新しく開かれたとき(起動したとき)に指定の関数(function)が実行されます。
今回は、スプレッドシートが起動したことを知らせるメールを送信するGASを作成してみたいと思います。
(1) メール送信GAS作成
スプレッドシートが起動したことを知らせるメールを作成・送信するGAS作成します。
メールの内容にはスプレッドシートのURLを含めたいと思います。
13行目ではスプレッドシートのURLを取得しています。 まずSpreadsheetApp.getActiveSpreadsheet()
でGASの紐づいているスプレッドシートのオブジェクトを取得できます。
取得したオブジェクトに対してgetUrl()
メソッドを実行すると、そのスプレッドシートのアクセスURLが文字列で得られます。
function sendMailOnOpen() {
const address = 'admin@example.com'; // メールの送付先
const subject = '【起動通知】スプレッドシート'; // メールの件名
const bodyTemplate = `
下記のスプレッドシートが起動しました。
スプレッドシートのURL:{url}
`;
// スプレッドシートのURLを取得します。
const url = SpreadsheetApp.getActiveSpreadsheet().getUrl();
let body = bodyTemplate
.replace('{url}', url)
GmailApp.sendEmail(address, subject, body);
}
(2) トリガーの作成
トリガーを作成し、画像のように設定します。
実行するデプロイを選択について:
ここで言うデプロイとは書き出されたバージョンを指し、Head
は保存されている最新のコードを意味します。
つまり上図で設定したトリガーは、以降コードを修正・変更しても常に最新の内容で実行してくれるということです。
逆に以降のコードの変更を反映して欲しくない場合は、トリガー設定前に「デプロイ」を行ってそのバージョンを指定することになります。
エラー通知設定について:
トリガーから実行されたコードでエラーが発生したとき、どれくらいの頻度でエラーが起きたことを通知するのか設定できます。
頻度の設定は4種類あるため、トリガーの動作頻度や緊急性によって設定します。(エラーが起きた場合すぐに対応が必要であれば「今すぐ」を選択するなど) 「今すぐ通知を受け取る」エラーが発生するとただちに通知します。
「1時間おきに通知を受け取る」エラーが発生すると1時間ごとにまとめて通知します。
「毎日通知を受け取る」エラーが発生すると1日1回まとめて通知します。
「1週間おきに通知を受け取る」エラーが発生すると1週間に1回まとめて通知します。
(3) 結果
スプレッドシートのタブを一度閉じてもう一度開くと、下記メールが届きました。
このときメールの送信元はGASを実行したアカウント(=トリガーで実行される場合はトリガーを作成したアカウント)になります。
実用例:
- ファイルを共有した後にちゃんとファイルを開いたか確認したい場合
- 予期しない時期にファイルが開かれていないか確認し、開いた場合には通知を受けたい場合
2. 「時間主導型」を用いた定期送信
今度はGASのトリガーのソース「時間主導型」を用います。
このトリガーでは、設定した期間毎に繰り返し指定した関数が実行されます。
今回は、10分おきにメールを送信するGASを作成してみたいと思います。
(1) 時間主導型メール送信用GAS作成
現在の時刻を添えてメールを作成・送信するGASを作成します。
今回は素のDate型を用いて現在時刻をフォーマットします。
Date型
とは:(下記コード3行目)
数値や文字列などと同じデータ型のひとつで、日付や時刻・タイムゾーンなどの情報を持ったデータです。new Date()
で現在日時のDate型データが取得できます。
素のまま文字列として表示するとWed Jul 21 2021 16:09:07 GMT+0900 (Japan Standard Time)
のような読みにくい形式で表示されてしまうので、整形(フォーマット)してあげる必要があります。
フォーマットや日時の比較・計算を簡単にするライブラリも数多く存在しますが、その紹介は別記事でしたいと思います。
Date型のフォーマットについて:
年月日や時間をそれぞれの要素ごとに取得して、文字列として合わせる方法を用いています。
注意点①:「月」は0から12カ月分の数字で取得されるため、+1
をしてあげる必要があります。(例:1月⇒0が得られる。2月⇒1が得られる。)
注意点②:「曜日」は0から7種類分の数字で取得されるため、表示したい文字の形に置き換えてあげる必要があります。下記ではSwitch文を用いて条件分岐しています。
function sendMailEvery10Minuts() {
const now = new Date();
const nowYearStr = now.getFullYear();
const nowMonthStr = now.getMonth() + 1;
const nowDateStr = now.getDate();
const nowHoursStr = now.getHours();
const nowMinutsStr = now.getMinutes();
const nowSecondsStr = now.getSeconds();
const nowDayNum = now.getDay();
var nowDayStr = '';
switch(nowDayNum){
case 0: nowDayStr = '日曜日'; break;
case 1: nowDayStr = '月曜日'; break;
case 2: nowDayStr = '火曜日'; break;
case 3: nowDayStr = '水曜日'; break;
case 4: nowDayStr = '木曜日'; break;
case 5: nowDayStr = '金曜日'; break;
case 6: nowDayStr = '土曜日'; break;
}
const nowStr = nowYearStr +'年'+ nowMonthStr +'月'+ nowDateStr +'日('+ nowDayStr +')'+ nowHoursStr +'時'+ nowMinutsStr +'分'+ nowSecondsStr +'秒';
const address = 'admin@example.com'; // メールの送付先
const subject = '【定期メール】'+ nowStr; // メールの件名
const bodyTemplate = `
10分おきにメールを送信しています。
現在の日時:{now}
`;
let body = bodyTemplate
.replace('{now}', nowStr)
GmailApp.sendEmail(address, subject, body);
}
(2) 時間主導型トリガーの作成
トリガーを作成し、画像のように設定します。
時間主導型のトリガーはトリガー設定後すぐには動作しません。
設定した期間経過後に1度目の実行がされるので、トリガーからの動作が心配な場合は一度短い期間のトリガーを作ってみて試してみると良いでしょう。
またこの「分ベースのタイマー」や「時間ベースのタイマー」の場合、毎時0分/10分/20分…のように実行時刻を設定することはできずトリガーを作成した時間から起算されます。
(例:12時3分に10分おきのトリガーを作成した場合、12時13分に実行される)
ちなみに「日付ベースのタイマー」については、「午前0時~1時」に実行といった形での設定になり何分に実行されるかはわかりません。
もし「必ず毎日〇時〇分にトリガー起動させたい」というような場合は「時間主導型(日付ベースのタイマー)」で毎日「時間主導型(特定の日時)」を作るといった対応が必要になります。(いつかこの内容の記事も作成できればと思います。)
(3) 時間主導型トリガー結果
10分おきにメールが届きました。
受信ボックス:
メール内容:
今回の例のような短いコードでは特に影響ありませんが、コードによっては実行にかかる時間が一定ではないため定期実行でもある程度のぶれが生じます。
実用例:
- 定例会のお知らせメールを毎週水曜日午後5時までに送信する場合(週ベースのタイマー/水曜日/午後3〜4時)
- 月締めのリマインドを毎月25日の10時までに送信する場合(月ベースのタイマー/25日/午前8〜9時)
- 一日一回出欠情報などのメールを送信する場合(日付ベースのタイマー/午前11〜12時)
3. 「時間主導型」を用いて条件ありの定期送信
先ほどと同様GASのトリガーのソース「時間主導型」を用います。
今度は、現在時刻を偶数奇数で判定して20分おきにメールを送信するGASを作成してみたいと思います。
※画面上で作成できる分ベースのタイマーのトリガーは「1分おき」「5分おき」「10分おき」「15分おき」「30分おき」のみ
(1) 条件付きメール送信用GAS作成
先ほどと同様に現在の時刻を取得し、20分おきにメールを作成・送信するGASを作成します。
0分台/20分台/40分台のときだけ送信することで20分おきとします。(下記コードの32行目~35行目参照)
function sendMailEvery20MinutsAtOdd() {
const now = new Date();
const nowYearStr = now.getFullYear();
const nowMonthStr = now.getMonth() + 1;
const nowDateStr = now.getDate();
const nowHoursStr = now.getHours();
const nowMinutsStr = now.getMinutes();
const nowSecondsStr = now.getSeconds();
const nowDayNum = now.getDay();
var nowDayStr = '';
switch(nowDayNum){
case 0: nowDayStr = '日曜日'; break;
case 1: nowDayStr = '月曜日'; break;
case 2: nowDayStr = '火曜日'; break;
case 3: nowDayStr = '水曜日'; break;
case 4: nowDayStr = '木曜日'; break;
case 5: nowDayStr = '金曜日'; break;
case 6: nowDayStr = '土曜日'; break;
}
const nowStr = nowYearStr +'年'+ nowMonthStr +'月'+ nowDateStr +'日('+ nowDayStr +')'+ nowHoursStr +'時'+ nowMinutsStr +'分'+ nowSecondsStr +'秒';
// ----ここより上は先ほどと同じ----
// 「分」を2桁表示に変換したものを取得(解説後述)
let nowMinutsDoubleDigit = ( '0' + nowMinutsStr ).slice( -2 );
// 十の位が偶数か判定し、メール作成&送信実行(解説後述)
if(Math.floor(nowMinutsDoubleDigit / 10) %2 == 0){
const address = 'admin@example.com'; // メールの送付先
const subject = '【定期メール】'+ nowStr; // メールの件名
const bodyTemplate = `
20分おきにメールを送信しています。
現在の日時:{now}
`;
let body = bodyTemplate
.replace('{now}', nowStr)
GmailApp.sendEmail(address, subject, body);
}
}
「分」を2桁表示に変換 解説:(32行目)
// 「分」を2桁表示に変換したものを取得(解説後述)
let nowMinutsDoubleDigit = ( '0' + nowMinutsStr ).slice( -2 );
nowMinutsStr
は0~59の数字です。そのため0~9は1桁表示となります。
20分おきの動作には、トリガーを10分おきに動作させて、十の位が偶数かどうかで判定をします。
そのため0~9分の際は、00~09という形にしないと十の位の文字が得られずエラーになります。
まず'0' + nowMinutsStr
とすることで、00~059の文字列になります。
更にこれの桁数ををslice(n)
メソッドを用いて整えます。slice(-2)
で下2桁になります。
※slice(n)
は指定した数字n
で文字列または配列を切り出すメソッドです。正の数で頭からn+1文字以降、負の数で後ろからn文字分。
2桁に整えた結果はnowMinutsDoubleDigit
に格納しました。
十の位が偶数か判定 解説:(35行目)
// 十の位が偶数か判定し、メール作成&送信実行(解説後述)
if(Math.floor(nowMinutsDoubleDigit / 10) %2 == 0){
//...以降省略
2桁に整えたnowMinutsDoubleDigit
の十の位の数字が偶数かどうか判定します。 まずはnowMinutsDoubleDigit / 10
で十の位が一の位になるようにします。(例:35⇒3.5)
つぎにMath.floor(n)
を用いて小数点以下を切り捨てます。(例:3.5⇒3)
そしてn % 2
で偶数かどうか判定します。偶数ならば結果は0(余りなし)です。(例:3 % 2⇒1)
今回は偶数のとき、つまり0分台/20分台/40分台の場合はメール作成&送信としたいので、== 0
の条件になります。
(2) 条件付き時間主導型トリガーの作成
トリガーを作成し、画像のように設定します。
先述のとおり10分おきのトリガーを作成します。
(3) 条件付き時間主導型トリガー結果
トリガーの実行は10分間隔で行われましたが、メールは20分おきに届きました。
トリガー実行結果:
受信ボックス:
まとめ
今回の例ではトリガーを用いてメールを送信するスクリプトを作成しました。
トリガーは画面上で設定できるものだけを用いたため、条件つきの例(20分おき)ではその制約のために変換や計算を挟みましたが、実はGASから作成するトリガーであればもっと簡単に任意の間隔で設定ができます。 GASから作成するトリガーについての内容も今後記事を追加していきたいと思います。