見出し画像

みんな大好き!?GASでGmailの下書きをスプレッドシートの宛先リストに一斉送信するスクリプト

ノンプロ研でGAS勉強中です。

色々できるようになるGASのなかでも、実務で使える or 使いたいランキング上位に入ってくるのがGmailとスプレッドシートを使ったメール一斉送信ではないでしょうか。

同じ内容の本文をリストの宛先に一斉送信したり、一部を差し込みでパーソナライズさせたメールを送信したりというのは、さらっとできるようになると結構便利です。

しかしこれはわざわざGASを使わなくても、mailchimpを代表としてメール配信サービスは多数あります。しかし…

・無料プランには制限がある
・多くが英語のみの操作画面
・高機能な分、設定・操作が複雑
・迷惑メールに入りがち
・Gmailのプロモーションタブに入りがち

などもあり、いつも使っているGmaiで一斉送信したいというニーズはあると思います。

そこでGASの登場…の前にGmailのアドオンで、まさに一斉送信が可能になる Mail merge for Gmail というアドオンがありまして、これを使えばわざわざGASを使用しなくても大丈夫です。

ほぼほぼ不満のないアドオンなのですが、もちろんこれほど高機能なものの全機能が無料であるわけがなく、無料プランだと1日あたりの送信数の制限(50件/日)があります。

またアドオンの制限以外にも、使っているGmailが個人向けGmailなのか、Google Workspaceと呼ばれる企業向けの有料アカウントなのかで、1日あたりの送信数の制限があります。

大量にメールを送信する必要があるケースにおいては、Gmailを使った一斉送信というのは向いていないかもしれません。

さて、この素敵アドオンの費用をけちって、100件/日(2021/03/28 現在の制限)程度のメールを一斉送信するためのスクリプトを書いてみました。

やりたいこと

・メールをスプレッドシートの宛先リストに一斉送信したい
・送信メールは下書きに保存したメールで指定した件名に一致するものを送信したい
・スプレッドシートに送信ボタンを付けたい
・ボタンを押した後に送信するかの確認ダイアログを出したい
・一斉送信する前に自分宛にテスト送信したい

です!

下書きに保存したメールから件名一致でひな形を取得

まずは一斉送信したいメールのひな形をいつもどおりにGmailで作成し、そのまま下書きへ。その際にユニークな件名をつけておきます。

その件名とスプレッドシートの指定セルに入力した文字列が一致するメールを取得する関数をまず用意しました。

// 下書き内のメールで指定した件名と一致するメールを取得する関数

function matchDraft(matchSubject) {
 const drafts = GmailApp.getDraftMessages();

// 下書きのメール群をひとつづつ取得して一致する場合のみ戻り値にメールオブジェクトを返す

 for (const draft of drafts) {
   if (draft.getSubject() === matchSubject) {
     console.log('一致')
     return draft;
     break;
   } else {
     console.log('不一致')
   }
 }
}

この関数にスプレッドシートで特定セルに記入して指定した件名を渡します。

// 件名と一致する下書きを取得して一斉送信関数にわたす関数
function mailDelivery() {

 //ボタンを押したときに関数を実行するかを確認する
 const confirmation = Browser.msgBox("メール一斉送信", "リストの顧客に一斉送信しますか?", Browser.Buttons.OK_CANCEL);

 if (confirmation == "cancel") {
   Browser.msgBox("操作をキャンセルしました。");
   return;
 }

 // スプレッドシートを取得
 const ss = SpreadsheetApp.getActiveSpreadsheet();

 // 今回送信する下書きメールの件名をスプレッドシートから取得
 const sheetEmail = ss.getSheetByName('Mail Delivery');
 const subejct = sheetEmail.getRange('B7').getValue();

 // 指定した件名と一致するメールをリストに一斉送信、ただし見つからない場合はエラーメッセージを出力
 const newEmail = matchDraft(subejct);
 if (newEmail === undefined) {
   Browser.msgBox('件名が一致するメールが見つかりません')
 } else {
   sendEmails(newEmail);
 }
}

これが、今回のメインの関数となります。

スプレッドシートに送信ボタンを付けて、ボタンを押した後に送信するかの確認ダイアログを出したい

スクリーンショット 2021-03-28 18.49.40

Excelのように図形(ボタン)をクリックした際にスクリプトを動作させるように仕込むことができますが、押した感があまり無いのに知らない間にスクリプトが実行されるということがありましたので、以下を参考にメッセージダイアログが出るようにしました。

メールをスプレッドシートの宛先リストに一斉送信する

件名一致する下書きが見つかった場合に一斉送信するsendEmailsと名付けた関数を実行します。

// メールを一斉送信する関数
function sendEmails(newEmail) {
 const ss = SpreadsheetApp.getActiveSpreadsheet();

 // メーリングリストのスプレッドシートを取得し顧客情報を配列で格納
 const sheetList = ss.getSheetByName('LIST');
 const listArray = sheetList.getDataRange().getValues();
 const numList = listArray.length;

 // メーリングリストのデータ数を取得して繰り返しメール配信
 for (let i = 1; i < numList; i++) {
   const recipient = listArray[i][2];
   const subejct = newEmail.getSubject();
   const plainBody = newEmail.getPlainBody();
   const htmlBody = newEmail.getBody();

   GmailApp.sendEmail(
     recipient,
     subejct,
     plainBody,
     { htmlBody: htmlBody }
   );
   Utilities.sleep(500);
 }
}

こんな感じです。今回はLISTというシート(ちなみに1行名はタイトル行)のC列にメールアドレスが記入されているので、宛先は

const recipient = listArray[i][2];

として取得しています。

参考にしたのはノンプロ研主宰の高橋さんの記事

必要な情報は、だいたいすでに載っています。

一斉送信する前に自分宛にテスト送信したい

上記の関数の焼き直しですが、自分宛てにテスト送信する関数も用意しました。

// テスト送信する関数
function testDelivery() {
 
 //ボタンを押したときに関数を実行するかを確認する
 const confirmation = Browser.msgBox("テスト送信", "自分宛にメールをテスト送信しますか?", Browser.Buttons.OK_CANCEL);

 if (confirmation == "cancel") {
   Browser.msgBox("操作をキャンセルしました。");
   return;
 }

 const ss = SpreadsheetApp.getActiveSpreadsheet();

 // 今回送信する下書きメールの件名をスプレッドシートから取得
 const sheetEmail = ss.getSheetByName('Mail Delivery');
 const subejct = sheetEmail.getRange('B7').getValue();

 // 指定した件名と一致するメールを自分宛てにテスト送信、ただし見つからない場合はエラーメッセージを出力
 const newEmail = matchDraft(subejct);
 if (newEmail === undefined) {
   Browser.msgBox('件名が一致するメールが見つかりません')
 } else {
   const recipient = 'xxxxxx@xxx.com'; // 自分のメールアドレス
   const subejct = 'テスト送信: ' + newEmail.getSubject();
   const plainBody = newEmail.getPlainBody();
   const htmlBody = newEmail.getBody();
   GmailApp.sendEmail(
     recipient,
     subejct,
     plainBody,
     { htmlBody: htmlBody }
   );
 }
}

これで完成。

おわりに

GASの勉強をはじめてはや2ヶ月ほど。とりあえず悪戦苦闘しながら、なんとなく動くものはできるものの、リーダブル(読みやすい)コードの道のりは険しいと感じてます。

・配列やオブジェクト
・関数の引数や戻り値

の理解がまだ腹落ちしていないため、毎度調べなおす羽目に。ただこうして実務で使えるツールができると楽しくなってきますね。



この記事が気に入ったらサポートをしてみませんか?