Gmail一斉送信・差し込み送信ツール(スプレッドシート)

Gmailを利用して業務を行う中で、下記のような要望をいただくことがあります。

  • メールを効率よく一斉送信したい
  • 宛名などの一部分だけ差し込みして送信したい
  • 添付ファイルを宛先ごとに変えたい

これらを解決する、一斉送信・差し込み送信ツールを作ってみましたので、公開します。

*このツールを使用したことにより、ご利用者様、または第三者に損害・トラブル等が発生した場合でも、一切の責任を負いません。自己責任の上でのご利用をお願いいたします。

ツールの概要

Googleスプレッドシートで作成したツールです。スプレッドシート上に作成したリストを使って、テキストや添付ファイルを差し込みし、一斉送信することができます。

ツールのメインシート
メインシートでは、メールのひな型入力や、送信の設定を行う
ツールのデータシート
データシートでは、宛先や差し込みテキスト、個別添付ファイルの設定を行う

上記画像のように設定すると、下記のように、一部分だけ内容が異なる(差し込まれている)メールを一斉送信することができます。

送信されたメール(サンプル)
ピンク色部分が、差し込まれたテキストや添付ファイル

* Gmailは1日に送信可能な件数などに制限があります。
  大量に送信する予定の場合は、Googleのヘルプをご確認ください。

使い方

ツールを自分用にコピーする

私が公開しているスプレッドシートを開き、コピーを作成します。

ファイルメニューからコピーを作成を選択
ファイル → コピーを作成
コピー先を指定する
この例では、マイドライブにコピーを作成しました

メールのテンプレート(ひな型)を作る

Mainシートの画面左のメールテンプレート部分に、基となるメールを作成しましょう。

メールテンプレート入力箇所
この部分に入力していく
発信者Emailあなたのメールアドレス
(エイリアスを設定している人は、そのアドレスでもOK)
発信者名あなたの名前(好きな名前にできます)
メールタイトルメールのタイトル
差し込みテキストを入れることも可能(後述します)
本文メールの本文
差し込みテキストを入れることも可能(後述します)
共通添付ファイル1~3全あて先に送付する添付ファイルのファイル名

メールタイトルと本文には、テキストの差し込みをすることができます。

例えば、「こんにちは、鈴木 太郎様」のように、あて先によって内容を変えたい場合に活用できます。

テキストを差し込む場所に、$0 ~ $9 のいずれかを入力してください。
イメージがつかみにくい場合は、下図をみていただければわかるかと思います。

テキストが差し込まれるイメージ
メール本文(またはタイトル)の $ 部分に、Dataシートの該当のテキストが差し込みされる

送り先データを作る

テンプレートができたら、次は、送り先データをDataシートに入力します。

送り先データの入力箇所
この部分に入力する
グループメール一斉送信の際は、送信対象にグループを指定することができます。
その場合は、この欄にグループ名を入力します。(必須ではありません)
宛先メールアドレス送信先のメールアドレス。
半角カンマで区切って複数入力することができます。
CCアドレスccに設定するメールアドレス。
半角カンマで区切って複数入力することができます。
BCCアドレスbccに設定するメールアドレス。
半角カンマで区切って複数入力することができます。
差込 $0~$9メールタイトルまたは本文に差し込むテキストを入力。
個別添付ファイル名1~3共通添付ファイルを以外のファイルを追加で添付したい場合は、ファイル名を入入力。
処理結果入力不要。

添付ファイルをGoogleドライブにアップロードする

メールにファイルを添付する場合は、添付ファイルをGoogleドライブにアップロードしておく必要があります。

このツールの仕様上、添付ファイルは全て同じフォルダに格納してください。

また、添付ファイルを格納したフォルダのIDを控えておいてください。(後で使用します)

フォルダIDの取得方法

送信設定する

続いて、送信設定を行います。

送信設定の入力箇所
ここに送信設定を入力する
添付ファイル格納フォルダID添付ファイルを格納したフォルダのID
(ファイルを添付しない場合は入力不要)
送信対象グループ一斉送信の対象とするグループの名前
(未指定の場合はDataシートの全宛先に送信します)
送信モードテスト送信 または 本番送信 を選択します。
テスト送信の場合、すべて発信者Email宛てに送信します。

送信する

ここまでの手順で準備は整いました。

メール送信をクリックすれば、メールが差し込み一斉送信されます。
処理が終了したら、Dataシート一番右の処理結果を必ず確認してください。

初めてこのツールを使う時は、承認作業を行う必要があります。
その手順は、過去の他の記事にまとめていますので、ご参照ください。

参考:GASソースコード

// *** メイン処理 ***
function sashikomiGmailSend(){

  // * スプレッドシートの取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const wsMain = ss.getSheetByName("Main");
  const wsData = ss.getSheetByName("Data");

  // * 処理結果列をクリアする
  wsData.getRange(2, 18, wsData.getMaxRows(), 18).clearContent();

  // * 送信設定の取得
  const folderId = wsMain.getRange("E2").getValue();
  const targetGroup = wsMain.getRange("E3").getValue();
  const sendMode = wsMain.getRange("E4").getValue() ? wsMain.getRange("E4").getValue() : "テスト送信";
  if ( sendMode !== "テスト送信" && sendMode !== "本番送信" ){
      Browser.msgBox("送信モードを選択してください");
      return;    
  }

  // * 実行確認メッセージ
  const select = Browser.msgBox( `${sendMode}モードでメールを一括送信します。よろしいですか?`, Browser.Buttons.OK_CANCEL);
  if (select == "cancel") {
      Browser.msgBox("キャンセルしました");
      return;
  }

  // * メールテンプレートの取得
  const senderEmail = wsMain.getRange("B2").getValue();
  const senderName = wsMain.getRange("B3").getValue();
  const title = wsMain.getRange("B4").getValue();
  const letterBody = wsMain.getRange("B5").getValue();

  // * メールテンプレート(共通添付ファイル)の取得
  const commonAttachments = [];
  for ( let row = 6; row <= 8; row++ ){
    const fileName = wsMain.getRange(row, 2).getValue();
    if ( fileName ){
      const response = getAttachement(folderId, fileName);
      if ( !response.errMsg ){ 
        commonAttachments.push(response.attachement);
      } else {
        Browser.msgBox(`${response.errMsg}処理を中断します。`);
        return;
      }
    }
  }

  // * 差込データの取得・メール送信
  const data = wsData.getDataRange().getValues();

  // 0件の場合は処理終了
  if ( data.length <= 1 ) {
      Browser.msgBox("送信対象が存在しないため、処理を中断します。");
      return;
  }

  for ( let i = 1; i < data.length; i++ ){
    // 送信対象グループの宛先 または 送信対象グループ未設定の場合はメール送信
    if ( data[i][0] === targetGroup || !targetGroup ){

      // 差込処理
      let recipient = data[i][1];
      const processedTitle = insertionText(title, data[i].slice(4,14));
      const processedLetterBody = insertionText(letterBody, data[i].slice(4,14));

      // 個別添付ファイルの取得
      const additionalAttachments = [];
      let additionalAttachmentsErrMsg = "";
      for ( let col = 14; col <= 16; col++ ){
        const fileName = data[i][col];
        if ( fileName ){
          const response = getAttachement(folderId, fileName);
          if ( !response.errMsg ){ 
            additionalAttachments.push(response.attachement);
          } else {
            additionalAttachmentsErrMsg = response.errMsg;
            break;
          }
        }
      }

      // 個別添付ファイルの取得エラー時はスキップする
      if ( additionalAttachmentsErrMsg ){
        wsData.getRange(i + 1, 18).setValue(additionalAttachmentsErrMsg);
        continue;
      }

      // テストモードの場合、処理継続するか確認し、あて先メールアドレスを送信者のアドレスに変更する
      if ( sendMode === "テスト送信" ){
        const select = Browser.msgBox(
          `<テストモード>Dataシート${i + 1}行目:${recipient}に送信予定のメールを${senderEmail}にテスト送信します。よろしいですか?`,
          Browser.Buttons.YES_NO
        );
        if (select == "no") {
            Browser.msgBox("テスト送信を中断しました。");
            break;
        }
        recipient = senderEmail;
      }

      // メール送信処理
      const options = {
        from: senderEmail,
        name: senderName
      };
      if ( data[i][2] ){ options.cc = data[i][2] };
      if ( data[i][3] ){ options.bcc = data[i][3] };
      if ( commonAttachments || additionalAttachments ){ options.attachments = commonAttachments.concat(additionalAttachments); }
      try {
        GmailApp.sendEmail( recipient, processedTitle, processedLetterBody, options );
        wsData.getRange(i + 1, 18).setValue(`送信成功(${sendMode})`);
      } catch(e) {
        wsData.getRange(i + 1, 18).setValue(`送信失敗(${sendMode}):${e}`);
      }
     
    } else {
      // 指定グループ以外の行の場合はスキップ
      wsData.getRange(i + 1, 18).setValue("送信対象外");
    }
  }
  
  // 終了メッセージ表示
  Browser.msgBox("処理が終了しました。処理結果は、Dataシートの「処理結果」列で確認してください。");
}

// *** フォルダID、ファイル名を元にファイルを取得する ***
function getAttachement(folderId, fileName){
  const response = {};
  const files = DriveApp.getFolderById(folderId).getFilesByName(fileName);
  if ( files.hasNext() ){
    response.attachement = files.next();
    if ( files.hasNext() ){
      // 名称が合致するファイルが複数あった場合は処理中断
      response.errMsg = `送信失敗:添付ファイル取得エラー・・・「${fileName}」が複数存在します。` ;
    }
  } else {
    // 名称が合致するファイルが存在しない場合は処理中断
    response.errMsg = `送信失敗:添付ファイル取得エラー・・・「${fileName}」が存在しません。`; 
  }
  return response;
}

// *** テンプレートテキストの$部分にテキストを差し込む ***
function insertionText(text, afterTexts){
  afterTexts.forEach( (afterText, index) => {
    const before = new RegExp("\\$" + index, "g");
    const after = afterText;
    text = text.replace(before, after);
  })
  return text;
}

コメント

  1. つるり より:

    はじめまして!
    最高のツールをありがとうございます。

    送信ではなく下書き保存をするように、GmailApp.createDraftに書き換えたバージョンも作って活用しています。

    1点質問させてください。
    テキストを差し込む変数の$0、$1….のコードが分かりませんでした。
    https://web-breeze.net/gas_sashikomi-gmail/ こちらのページのコードであれば理解できたのですが…。

    と言いますのも、アメリカ向けの作業で金額をメールに記載すルケースが多く、$0などの文字列が変数になっていると、誤変換されてしまいます。

    • ichi3270 ichi3270 より:

      確かに、ドルで金額を示すケースですと使えなくなってしまいますね・・・

      差し込み用の変数を$0、$1・・・ではなく、★1、★2・・・にするという方法はどうでしょう。

      const before = new RegExp("\\$" + index, "g");

      上記の部分を

      const before = new RegExp("★" + index, "g");

      というコードに書き換えてお試しいただければと思います。

      • つるり より:

        いけました!
        変数を指定しているコードがイマイチ分かっていなかったため、明示いただけてすんなり解決しました。

  2. デモメンバー より:

    早速試してみたのですが、少し補足説明をよろしくお願いします。

    すべての送信者に、同じファイルを添付する場合は、メインシート欄にある、共通テンプシートの所に、ファイルを設定するかと思いますが、ファイルを設定の仕方がわかりません。
    以前は、グーグルドライブに添付ファイルを置いておき、そのファイルのリンクをコピーで必要な文字列をコピペして置いていたのですが、その方法では、送信されていませんでした。

    なので、添付ファイルをGoogleドライブの同じフォルダにアップロードして、メインシート欄にある、添付ファイル格納フォルダIDにグーグルドライブの必要な文字列を記入して、先ほどの共通添付シート欄は空欄にしてみたのですが、それでもファイルを添付したメールを送信できませんでした。

    改めて、添付ファイルの補足説明をいただけると助かります。よろしくお願いします。

    • ichi3270 ichi3270 より:

      以前の記事のツールとは使い方が少し変わっていますので、詳細はこの記事をご覧いただければと思います。
      添付ファイルについては、下記3点が要点になります。
      1.添付ファイルをGoogleドライブ上の1つのフォルダに入れてください
      2.ツール右上の「添付ファイル格納フォルダID」にフォルダのIDを入れてください
      3.ツール内の添付ファイルを入力する欄には、IDではなくファイル名を入力してください。

  3. 山脇 より:

    一点質問です。

    メールを送信する際に
    <テストモード>Dataシート●●行目:●●@●●.jpに送信予定のメールを●●@●●.jpにテスト送信します。よろしいですか?
    という文言が出てきて、はいを押すと送信されると思うのですが、
    たとえば50人に一斉送信をする際、上記のポップアップが50回表示され、
    50回はいを押さないと送信されません。(結構時間がかかります。)
    この動作を省く方法はございますか?

    • 山脇 より:

      すみません、もう一点なのですが、
      DataシートのB列、宛先メールアドレスに
      送信先のメールアドレスを入力しても、
      その方にメールが飛ばず自分のメールアドレスがtoになってしまいます。

      • ichi3270 ichi3270 より:

        どちらのご質問も、「テスト送信」モードで実行されているためだと思います。
        「テスト送信」で送信されるメールのイメージを確認できたら、「本番送信」に切り替えて実行してください。

  4. りら より:

    質問になります。
    本文中の文字色・サイズ・太字等を反映させることは可能でしょうか。
    教えて頂けますと幸いです。

    • ichi3270 ichi3270 より:

      ご期待に沿えず申し訳ないのですが、このツールそのままでは文字の書式等を設定することができません。
      Google Apps ScriptでHTMLメールを送信することは可能なようですので、もしツールの修正にチャレンジされる場合はこちらの記事が参考になりそうかと思いました。

  5. k より:

    公開いただいてるツールですとファイルは3つまで添付できますが、それ以上増やすことは出来ますでしょうか。もし可能であればやり方をご教示いただけますと幸いです。

    • ichi3270 ichi3270 より:

      例えば、共通添付ファイルを5つにしたい場合は・・・
      Mainシートの9行目、10行目に共通添付ファイル4、5の入力欄を作る
      ②スクリプトエディタから、下記部分のソースを修正する

      ・修正前

      for ( let row = 6; row <= 8; row++ ){

      ・修正後

      for ( let row = 6; row <= 10; row++ ){

      row = 6; row <= 10 は 6~10行目が添付ファイルの入力欄であることを意味していますので、5つより更に多くする場合は、10の部分の数字を増やしてください。 * 検証せずにコメントしていますので、実施される場合は必ずテスト送信をしてください。

  6. つるり より:

    とても助かっています!
    たまにファイルが添付されないケースがあります。ファイル名が違ったり、格納フォルダIDが間違っていることが原因です。
    一つでもファイル添付がされない場合は、エラーでストップするようには出来ないでしょうか?

    P.S. 送信ボタンに加え、下書き作成ボタンを追加して使用しています。上記のエラーを防ぐこともありますが、メール本文の装飾や、送信前の最終確認に使用しています。

    • ichi3270 ichi3270 より:

      ご指摘ありがとうございます。
      共通添付ファイルの誤り時はストップする仕様だったのですが、個別添付ファイルの誤り時にはそのまま送信されるようになっていました。
      公開しているツールを修正、ブログに掲載しているコードを修正しました。

  7. 岡本 より:

    便利なツールを提供いただきありがとうございます。
    送信を行い、結果をみると毎回Exception: 無効な引数というエラーにより送信失敗してしまいます。

    どのような可能性が考えられるでしょうか?
    送信先数は1400件ほど。Googleworkspaceを使用しているので、ドメインがgmail.com
    ではないです。

  8. yama より:

    とても便利なツールを公開していただきありがとうございます!
    とても助かっています!

    1点質問がありまして、

    添付ファイルのエクセルやワードにも
    変数差し込みすることは可能でしょうか?

    もし可能であればやり方をご教示いただけますと幸いです。

タイトルとURLをコピーしました