【備忘録】GASでGmailの下書きを作成して、スプレッドシートから自動でGmailタブを表示する【指定したURLのタブを開く】


# 背景

とある業務改善のため、GASでメールの下書きを自動生成するツールを作成していました。
その際に、Gmailのタブを新しく生成して表示できたら便利だなと思っていたところ……いけました！

実際に動かすとこのようになります。
![スクリーンショット 2022-12-15 11.04.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169385/53ef8522-d713-8383-1870-d671544bdf6f.png)

![スクリーンショット 2022-12-15 11.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169385/68f341cc-3653-cf69-3bd2-93dd020dc3ac.png)

![スクリーンショット 2022-12-15 11.04.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169385/ac9031fd-2a00-6d37-994c-3c4d583bb28f.png)



# この記事を読んで得られる知見

+ Gmailの下書きをGASで作成する
+ GASで特定のURLを自動で新しいタブで開くことができる

# 環境・使用ツール

+ GASスクリプトエディタ

## コード全体の紹介


このようなシートの形式になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2169385/5831dcb6-971f-ac63-3c8c-1a0c4b0cc268.png)


```javascript
function createMailDraft(){
  class WindowOperator {
    /**
    * Gmailの下書きURLをHTMLのscript要素としてモーダルダイアログ上で実行する
    */
    openGmailWindow() {
      const url = "https://mail.google.com/mail/u/0/?tab=rm&ogbl#drafts"; // 新しくタブで開くURLを入力
      const script = "<script>window.open('" + url + "', '_blank').focus();google.script.host.close();</script>";
      const html = HtmlService.createHtmlOutput(script);
      SpreadsheetApp.getUi().showModalDialog(html, 'Gmail タブを開きます');
    }
    /**
    * 送信先の名前一覧をダイアログで表示して確認する
    */
    showCheckDialog(name_list) {
      const msg=name_list.join("さん,")+"さんのメール下書きを作成しますか？"
      // 動作の許可をメッセージで確認
      const select = Browser.msgBox( msg, Browser.Buttons.OK_CANCEL);
      if (select == "cancel") {
          Browser.msgBox("キャンセルしました");
          return false;
      }
      return true;
    }
  }

  class Recipients {
    /**
    * Recipientsクラスを作成
    * @param {5 × n array} sheet_value - スプレッドシートから取得した生徒情報
    */
    constructor(sheet_value) {
      this.recipient_list=[]
      this.name_list=[]
      for (let value of sheet_value) {
        if (!value[4]) continue;
        const recipient = {"last_name":value[0], "first_name":value[1],"mail_address":value[2],"mentor_name":value[3]};
        this.recipient_list.push(recipient);
        this.name_list.push(recipient["last_name"]);
      }
    }
  }

  class MailScript {
    /**
    * MailScriptクラスを作成
    * @param {dict} recipient - 送信先情報
    */
    constructor(recipient) {
      this.mail_address = recipient.mail_address;
      this.from_mail = "watashi@de.su";
      this.subject = recipient.first_name+"さん　本日のお天気について";
      this.original_body = "%s 様\n\nお世話になっております。\n%sです。\n\n本日は良い天気ですね。";
      this.body = Utilities.formatString(this.original_body,recipient.last_name,recipient.mentor_name,recipient.first_name);
    }
    
    /**
    * メール文面を作成
    */
    createDraft() {
      let options ={
        from: this.from_mail,
        bcc:this.from_mail
      };
      GmailApp.createDraft(this.mail_address,this.subject,this.body,options);
      return;
    }
  }
  // シートを取得
  const url = PropertiesService.getScriptProperties().getProperty("SSTR_URL"); // 操作元のURL
  const sheetName = 'メール作成';
  const sheet = SpreadsheetApp.openByUrl(url).getSheetByName(sheetName);
  // シート上の全データを取得
  const max_row = sheet.getLastRow();
  const max_col = sheet.getLastColumn();
  const values = sheet.getSheetValues(2, 1, max_row-1, max_col);

  const recipients = new Recipients(values);
  const windowOperator = new WindowOperator();

  // ダイアログで実行するか確認し、OKなら処理を実行
  if (windowOperator.showCheckDialog(recipients.name_list)) {
    // 送信先情報を順に取り出して下書き作成
    for (recipient of recipients.recipient_list) {
      let mail = new MailScript(recipient);
      mail.createDraft();
    }
    // Gmailタブを開く
    windowOperator.openGmailWindow();
  }
}
```
:::note
シートのURLはGASのスクリプトプロパティに格納しています。
やり方は[こちら](https://qiita.com/iorn121/items/6881b4766dca543d46e9#%E9%87%8D%E8%A6%81%E3%81%AA%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AB%E6%A0%BC%E7%B4%8D%E3%81%97%E3%81%A6%E7%A7%98%E5%8C%BF%E3%81%99%E3%82%8B)に記載しています。
:::
:::note warn
[こちら](https://qiita.com/iorn121/items/6881b4766dca543d46e9#%E9%87%8D%E8%A6%81%E3%81%AA%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AB%E6%A0%BC%E7%B4%8D%E3%81%97%E3%81%A6%E7%A7%98%E5%8C%BF%E3%81%99%E3%82%8B)にも書いているように、ファイルと紐づいたContainer-bound Scriptsと、独立して作成されるStandalone Scriptsの２種類があります。
今回のGASはバインドされていないといけません。
:::

## 処理の流れ

1. 操作元のシートを取得して、シート上のデータを取得します
1. Recipientsインスタンスを作成して、送信先情報の配列と送信先名の配列を作成します
1. WindowOperatorインスタンスを作成して、UI操作関連をできるようにします
1. showCheckDialog関数で送信先名からメッセージを作成し、下書きの作成をしてよいかダイアログで確認します
1. もしOKなら送信先情報の配列から1件ずつデータを取り出し、createDraft関数で下書きを作成していきます
1. 処理が完了したらopenGmailWindow関数を実行してGmail下書きウィンドウを新しいタブで開きます



# 最後に
GASで新しいタブを開けるのは、多くの人に使ってもらいやすくなりそうで便利だと思いました。


# 参考資料

+ 公式ドキュメント：https://developers.google.com/apps-script/reference/gmail/gmail-app
+ JSDoc：https://jsdoc.app/howto-es2015-classes.html
+ https://teratail.com/questions/164151