Site cover image

ふつうのITエンジニアの独り言

本業はAndroidとiPhoneのアプリ開発のエンジニアです。将来はフリーランスで海の近くで妻とのんびり暮らすことを夢見て、幅広くIT技術に触れていきたいと思います。このブログはその備忘録と私のポートフォリオとして活動記録を記すものです。

自分の死後に嫁や子どもにメッセージを自動で配信するサービスをタダで用意したい(その3) ~生存確認メールの配信システムを作成する~

目次


生存確認メールの仕様を詰める


 生存確認メールは、最後の確認から一定の期間が経過したときに送信する。生存確認メールが頻繁に送信されて、都度確認を行わないと行けないのは面倒なので、今回のシステムでは一ヶ月に一回の生存確認を行えばよいものとする。

 一回の生存確認期間は、月の1日から月の終わりまでとし、その月の間に一度でも生存確認が取れていれば良いものとする。もし生存確認が取れていない場合は、翌月の1日にメッセージが配信される。これは、仮に8/1に生存確認を行って8/2に事故死してしまった場合、8月は生存判定となるので、9/1にはメッセージ配信されず、10/1にメッセージ配信されるため、死亡から約2ヶ月間は配信されないことになる。最長で2ヶ月間メッセージの配信までに遅延が発生する可能性があるが、そもそも緊急性のあるメッセージは本システムではサポートできないので、そういったメッセージは別の手段で伝えることを検討した方が良い。

 別の方法として、最後の生存確認から一定期間が経過したときにメッセージ配信という方法もあるが、これだと生存確認のペースは一ヶ月よりも短いものになってしまう。メッセージ配信されてしまう前日に生存確認を必ず行うという意志があればよいが、一度でも生存確認を忘れてしまうと大変なことになるので、遅くても配信の一週間前には生存確認を行っておきたいからである。

 シンプルに以下の仕様で実装することにする。

仕様
その月の生存確認が行われていない場合のみ、メール配信を行う。
メール配信は、指定された日に配信する。
配信日はスプレッドシートの設定にて管理し、複数の日を選択できるようにする。
毎日、決まった時間にメール配信のチェックを行い、生存確認メールの送信が必要であれば、そのチェックのタイミングで送信する。

実装


メール送信の実装

 GASで任意のアドレスにメールを送信するメソッドを実装する。メールの送信は、GmailAppを使うと簡単に実装できた。メールの送信元は自分のGoogleアカウントになるが、TOに同じメールアドレスを設定しても、自分宛てにメールは届く。

/**
 * メールを送信する
 */
function sendChackMail(){
	let to = "<メールアドレス>"; // 生存確認の送信先アドレス
  let subject = "定期確認URL"; // メールタイトル
  let body = "https://script.google.com/macros/s/xxx/exec"; //確認用URL

  GmailApp.sendEmail(to, subject, body);
}

送信する日を設定するシートの作成

スプレッドシートにSendMailDayというシートを作成した。このシートでは、A列に日を、B列には送信したい日を選択できるように作成した。”送信”となっている日が、生存確認メールの送信日で、私の場合は月の後半に重点的に送信されるように設定しておいた。これで、生存確認が漏れるケースは防げるはず。

メールの送信判定の実現

 前回実装した生存確認のログから、最後アクセス月を取得する関数を用意した。ここで工夫した点は、もし何らかの不手際で生存確認ログのシートが削除されてしまった場合に、異常が検出できるようにnullを返すようにしていること。また、最終アクセスがまだ記録されていない場合は、0月を返すようにした。

 この関数の注意として、プログラミングの世界では、月は0~11月というように0始まりであることが多い。日は1始まりなのにである。この関数では、月は1~12の範囲で返すようにしている。

/**
 * 最終アクセスの月を取得する
 * @return {Number} 0:アクセス記録なし, 1~12:最終アクセス月, null:シートが無い
 */
function getLastMonthOfAccess(){
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SurvivalCheckLog");
  if( sheet == null ){
    return null;
  }

  const lastLog = sheet.getRange(1,1).getValue();
  if(lastLog == null || lastLog == ""){
    return 0; // 記録されていない場合は0月を返す
  }else{
    const date = new Date(lastLog);
    const month = date.getMonth() + 1;
    return month;
  }
}

 続いて、最終アクセス月と、送信日の設定からメール送信の可否を判断して、メールを送信するメソッドを用意した。このメソッドはまだ改善の余地があると思っている。例えば意図せずシートを削除してしまった場合に、生存確認のメールが送信されなくなってします。そうなると、知らず知らずのうちに死亡判定となってしまう可能性もある。そこで、異常を知らせるメールを配信するような仕様を入れておくと安心できそうだ。

/**
 * [SendMailDay]を確認して、生存確認メールを送る日であればメールを送る
 */
function checkAccessAndSendMail() {
  const date = new Date();
  const lastAccessMonth = getLastMonthOfAccess();
  if( lastAccessMonth == null){
	  // 最終アクセス月が取得できなかった
    return;
  }

  if( date.getMonth() == lastAccessMonth - 1){
	  // 最終アクセス月が今月の場合
    return;
  }

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SendMailDay");
  if(sheet == null){
	  // 送信日のシートが取得できなかった。
  }else{
    // 今日の日を取得
    const day = new Date().getDate();

    // 送信の可否をチェックする
    const sendFlg = sheet.getRange(day+1, 2).getValue();
	  if( sendFlg != "" ){
	    // 生存確認メール送信
      sendChackMail();
    }else{
    }
  }
}

GASタイマーのトリガーを設定する

 生存確認メールを送信するために、毎日決まった時間に送信チェックを行い、自動でメールが配信されるようにする。まずは、GASのエディタの左側メニューからトリガーを選択する

 右下のトリガーを追加のボタンをクリックすると、トリガーの設定画面が表示される。

 実行する関数には、先ほど作成した”checkAccessAndSendMail”を選択し、イベントのソートは時間主導型を選択した。今回は、毎日決まった時間にチェックを行い、メール送信を行いたいので、日付ベースのタイマーとして、メールが送信された時に、自分がすぐ気付けそうな時間帯として、12時ごろを設定した。

 この設定で保存することで、毎日きまった時間に、”checkAccessAndSendMail”が呼び出されるようになる。

 以上の設定をして、しばらく期待通りにメールが届くのかをテストする。

まとめ


 今回は、Google Apps Scriptのタイマーを用いて、任意のタイミングでメール送信の可否を判定し、メールを配信する仕組みを構築した。ここまでで生存確認システムは一通り完成したと思う。次回は、各種設定をスプレッドシートからではなく、Webアプリとしてブラウザから設定を編集できるようにしていきたい。