Googleのサービスだけでメールの一括送信ツールを作ってみた。

#1 初めに＋作ることになった経緯
メールの一括送信ツールを作成した話を投稿します。
*今回が初の投稿になります。技術的に未熟な点が多々ありますのでご容赦ください。

経緯としてはとある案件の最中、顧客と連絡が全然つかない状態になり、
質問の回答待ちで作業がストップ。。。（進捗的には全然大丈夫だった)

そんな時にメールの一括送信ツールを用意してほしいと依頼を受けました。

#2 構成
##2-1 条件や要望
ツールを用意するにあたって、いくつか条件・要望がありました。
・フリーソフトの使用は×
・自作でも、新規でPCにダウンロード・インストールが必要なものは×
・使いやすいツールが欲しい【意味深】
・ヒアリングした結果、ツール使用者の端末にはブラウザとメーラーくらいしか入ってない
##2-2 そしてこうなった。
今回はとりあえずGoogleアカウントとブラウザさえあれば使えるように
・Googleドライブ(ツール格納場所)
・Googleスプレッドシート(宛先の管理)
・Googleドキュメント(メール本文の管理)
・GAS(メール送信等の実行処理)
という構成にしました。

正直、Googleドキュメントは不要かなと思っていたのですが、
ツール使用者の文章スキルを考慮し、わざとこういう構成にしました。
(スペルチェックや確認等々ちゃんとしましょうね。という意味で)

#3 作成
##3-1 スプレッドシートの作成
![スクリーンショット (1).png](https://qiita-image-store.s3.amazonaws.com/0/309466/2343b0b9-47a9-4dfe-c935-8ee31344d1ce.png)
使用方法シートには使用方法と
送信するメールの件名＋本文のドキュメントID、送信実行のボタン

後に送信ボタンとGASを紐づけします。

![スクリーンショット (2).png](https://qiita-image-store.s3.amazonaws.com/0/309466/99b26452-cfd1-a1c4-f1a4-3f09fd93b1b1.png)
宛先シートには送信対象の情報を書いていきます。
メールを送りたくない相手には抑止欄に×をつけることとします。

##3-2 ドキュメントの作成
![スクリーンショット (3).png](https://qiita-image-store.s3.amazonaws.com/0/309466/74c9f997-367a-0613-7cce-e58c44fc94c3.png)
送りたい本文の内容を書くだけです。
ドキュメントIDを控えて前述のスプレッドシートに記載しておきましょう。

##3-3 GASの作成
3-1で作成したスプレッドシートの送信ボタンを右クリック→スクリプトを割り当て
適当に関数名をつけて作成を開始します。
私は「onClickSendMailButton」としておきました。

```コード.gs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('使用方法');
var docId = sheet.getRange(6, 2).getValue();
var mailTitle = sheet.getRange(8, 2).getValue();
var mailBody = "";
var mailHeader = "";
var docObj = null;
 
var addressSheet = ss.getSheetByName('宛先');
var sendList = [];
 
function onClickSendMailButton() {
  //★main★
  Logger.log("★★onClickSendMailButton★★") 
  
  inputCheck();
  readAddress();
  confirm();
  sendMail();
  
  Browser.msgBox("送信完了しました。");
}
 
function inputCheck() {
  Logger.log("★★inputCheck★★");  
  
  try {
    //ドキュメントをIDで取得
    docObj = DocumentApp.openById(docId); 
  } catch(e) {
    Browser.msgBox("指定されたドキュメントIDが正しくありません。");
    throw new Error("inputCheck:Error:" + e);
  }
 
}
 
function readAddress() {
  //宛先作成
  Logger.log("★★readAddress★★");
  var maxRow = maxRowCount();
  
  for (var i = 2; i <= maxRow; i++) {
    if(addressSheet.getRange(i, 2).getValue() != "×"
       && addressSheet.getRange(i, 3).getValue() != ""
       && addressSheet.getRange(i, 4).getValue() != ""
       && addressSheet.getRange(i, 5).getValue() != ""){
      
       sendList.push([addressSheet.getRange(i, 3).getValue(),addressSheet.getRange(i, 4).getValue(),addressSheet.getRange(i, 5).getValue()]);
       
    }
  }
}
 
function maxRowCount() {
  //入力最終行を求める
  Logger.log("★★maxRowCount★★");
  var i = 2;
  
  while (addressSheet.getRange(i, 1).getValue() != "") {
    i++;
  }
  
  i = i - 1;
  Logger.log("★★max★★:" + i);
  return i;
  
}
 
function confirm() {
  //送信前の確認
  Logger.log("★★confirm★★");
  
  var temp = "送信する本文は以下の通りです。\\n(詳細はメール本文、または宛先を確認してください。)\\n";
  Browser.msgBox(temp + docObj.getBody().getText());
 
  temp = "以下のアドレスに送信します。よろしいですか。(全" + sendList.length +　"件)\\n";
  for (var i = 0; i < sendList.length; i++) {
    temp = temp + "(" + sendList[i][0] + ")" + sendList[i][1] + ":" + " " + sendList[i][2] + "\\n"
  }
  var res = Browser.msgBox(temp, Browser.Buttons.OK_CANCEL);
  if (res === "cancel"){
    throw new Error("confirm:cancel");
  }
  
  temp = "メール送信を開始します。よろしいですね。【再確認】\\n【OKを押すと一斉送信が始まります。】";
  res = Browser.msgBox(temp, Browser.Buttons.OK_CANCEL);
  if (res === "cancel"){
    throw new Error("confirm:cancel");
  }
 
}
 
function sendMail() {
  Logger.log("★★sendMail★★");
  
  //宛先の名前
  mailHeader = "";
  
  //本文
  mailBody = docObj.getBody().getText();
  
  for (var i = 0; i < sendList.length; i++) {
    mailHeader = sendList[i][0] + " " + sendList[i][1] + "様\n\n"
    
    GmailApp.sendEmail(sendList[i][2],mailTitle,(mailHeader + mailBody));
  }
  
}
```
エラー投げるのと確認ダイアログは無駄に出してます。
業務とかだったらメールは1通1通が重いですからね・・・・。
GAS自体書くのは初めてでしたがさらっとかけました。

GASのタイムアウトが6分、メール送信の実行制限がたしか2,000/1日(アカウントの種類で差異あり)
なのでこの程度なら大丈夫だろうと見てます。

#4 実行
宛先、本文の入力が終了したら送信ボタンを押すだけです。
初回は許可とかを求められます。許可してあげてください。

#5 終わりに
できましたよ～と、依頼者に渡したらおおすげぇってなってました。
報酬はいろいろ理由をつけられてまだもらえていません(憤怒)