メール送信業務自動化システムの開発

# はじめに
こんにちは、Tastuyaです。現在は会津大学に通っており、学部3年生でトライアスロン部に所属しており、大学からプログラミングを始めました。これから大学３年間で開発してきたものの発信等を行なっていく予定なのでよろしくお願いいたします。

# 今回紹介する開発物
今回は学部3年の9月に開発した(最近までたまに修繕作業行っていましたが...)メール自動送信システムの紹介をしたいと思います。

# 開発のきっかけ
私が所属しているトライアスロン部では、毎日の練習メニューや出欠確認などのメール送信が必要でした。この繰り返しの作業を効率化するため、プログラミングを活用して自動化システムの開発に着手しました。

※もともとこのシステムに近しいものは部活の先輩が開発してたがその方が卒業される＋一部機能で問題がある＋自分自身追加したい機能がある（この追加機能はメール送信業務とは別の開発物に関わるものなのでそれに関しては近日別の記事で書きたいと思います。）

・普段送信しているメールの内容を一部紹介
![スクリーンショット 2024-01-20 21.04.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2573573/2c4aed2f-f519-6657-7fde-d522d22eeeb3.png)


# 使用ツール
・Googleスプレッドシート
・Google Apps Script

Google Apps Script（以降Gasと呼ぶ）は

「無料で利用可能」
「Googleアカウントさえあれば誰でも開発可能（つまり細かい環境構築が不要）」
「私が大学卒業後も部活動内でシステムの引き継ぎが容易」

という点から採用しました。


# メールが自動送信されるまでの流れ
スプレッドシートはこんな感じです。さすがに練習メニューの決定は人間がやる必要があるのでここだけは事前に部員が設定する必要があります。
![スクリーンショット 2024-01-20 21.15.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2573573/e0e42f47-9a82-763e-1555-73692068b5e2.png)

次のコードを使用してスプレッドシートを取得してメール送信を行っていきます（スプレッドシートの直接的なコードは今回は省略）。
```js:teamScheduleManager.gs
function tomorrow_detail() {
  const tm = tomorrow_menu();
  var message = "";
  var count = 1;
  for (let i = tm.count_start; i < tm.count_end; i++) {
    if (tm.count_end >= 3) {
      message += ("<strong style='color:red;'>" + count + "種目目</strong><br>");
      count++;
    }
    message += "明日の活動について連絡します。<br>明日は" + menu[i].event;
    if (menu[i].event == "ラン" || menu[i].event == "バイク" || menu[i].event == "スイム") {
      message += "練です。<br>";
    }
    else {
      message += "(" + menu[i].detail + ")です。<br>";
    }
    if (menu[i].event == "ラン") {
      message += config.runMessage
      message += "<br>"
    }
    else if (menu[i].event == "バイク") {
      message += config.bikeMessage
      message += "<br>"
      message += "以下は明日の参加者です。<br><br>"
      message += "選手:<br>"
      var tomorrow = new Date();
      tomorrow.setDate(tomorrow.getDate() + 1);
      tomorrow = tomorrow.toISOString().slice(0, 10);
      const bikeSheet = sheet(tomorrow);
      var dataRange = bikeSheet.getDataRange();
      var data = dataRange.getValues();
      var manageMember = []
      var mCount = 0;
      for (let i = 0; i < data.length; i++) {
        if (data[i][2] == "選手") {
          message += (data[i][1] + "<br>")
        }
        else if (data[i][2] == "マネージャー") {
          manageMember[mCount++] = data[i][1]
        }
      }
      message += "<br>マネージャー:<br>"
      for (let i = 0; i < manageMember.length; i++) {
        message += (manageMember[i] + "<br>")
      }
    }
    message += "<br>"

    if (menu[i].event == "ラン" || menu[i].event == "スイム" || menu[i].event == "バイク") {
      var place = menu[i].place;
      if (menu[i].event == "バイク") {
        place = config.bikePlace;
      }
      message += (menu[i].addComent + "<br><br>");
      message += "以下詳細です。<br><br>"
      message += "-------------------------<br>"
      message += ("種目: " + menu[i].event + "<br>")

      message += ("メイン: <a href='" + config.dayMenuLink + "'>" + menu[i].detail + "</a><br>")
      message += ("集合時間: " + menu[i].time + "<br>")
      message += ("集合場所: " + place + "<br>")
      if (menu[i].event == "バイク") {
        message += ("行き先: " + menu[i].place + "<br>")
      }
      message += "-------------------------<br><br>"
    }

    else if (menu[i].event == "大会" || menu[i].event == "イベント") {
      message += "詳しい内容は別途送られているメール等でご確認ください。<br><br>"
    }

  }
  message += whosMail("競技部長")
  return message;
}
```
```js:mail.gs
function everyDayMail() {
  var message = tomorrow_detail();
  var tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  tomorrow = tomorrow.toISOString().slice(0, 10);
  var checkEvent;
  for (let i = 0; i < menu.length; i++) {
    if (menu[i].date == tomorrow) {
      checkEvent = menu[i].event;
      break
    }
  }
  
  if (checkEvent != "休み") {
    MailApp.sendEmail({
      to: config.sendMember,
      subject: (config.title + config.nextdayTitle),
      htmlBody: message
    });
  }
}
```

このeveryDayMail()関数をGasのトリガーを使用して毎日昼頃に自動実行するようにします。
すると毎日昼頃に明日の練習が休みでない限り以下のようなメールが送信されます。
<img  width="70%" height="75px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2573573/4a81d6a9-21d7-a24a-813b-e8c7d979c739.png">

他にも今回は割愛しますが、翌週の練習メニューの表示メール・練習参加確認メール、スプレッドシートで取得した日にちの部分にまだ練習メニューが登録されていなかった場合の事前エラーメールなどのメールも定期的にメール送信するようになっています。


# おわりに
今回このシステム開発をしてみて、まず私の部員が４０人ほどが所属しているということもあり、その方々に対して自身のシステムを実装するとなるとかなり緊張感を持ちました。
結構今年は部活のためにこれ以外にも大学または独学で学んだスキルを活かして様々なことをおこなってきたのでそれの紹介もしたいと思います。

乞うご期待です（笑）！！