4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GASで宛先・本文が違うメールを一斉送信

Last updated at Posted at 2020-05-14

こんばんは、@0yanです。
今日は経営企画のお手伝いで、宛先一人ひとりに本文が微妙に違うメールをGmailで一斉送信するためのコードを書きました。
JavaScriptもGASも初心者かつ滅多に触らないので多少苦労しましたが、良い機会だったので、それぞれの言語の備忘録も兼ねて記事にまとめることにしました。
同じことをやりたい人のお役に立てば幸いです。

やりたかったこと

スプレッドシートに

  • 名前
  • 会社名
  • E-mail
  • 送信URL

を記載したシートを用意します。
image.png

そのうえでスクリプトを実行すると、下図赤枠部分が宛先毎に異なるメールを一斉送信できる・・・これがやりたかったことです。

image.png

コード全体像

先にコード全体を提示してしまいます。

function sendQuestionnaire() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('シート1');
  const dataRange = sheet.getDataRange();
  
  // 名前、会社名、E-mail、送信用URLの列数を取得(列数固定だと、列数が変わったときに機能しなくなるため)
  let nameIndex = 0;
  let companyNameIndex = 0;
  let emailIndex = 0;
  let sendUrlIndex = 0;
  for (var i = 1; i <= dataRange.getNumColumns(); i++) {
    switch (sheet.getRange(row=1, column=i).getValue()) {
      case '名前':
        nameIndex = i -1;  // 二次元配列のループは0から始まるため、列数を -1 する(以下同様)
      case '会社名':
        companyNameIndex = i -1; 
      case 'E-mail':
        emailIndex = i -1;
      case '送信URL':
        sendUrlIndex = i -1;
      default:
        ;
    }
  }
    
  // E-mail送信
  const subject = 'アンケートご協力のお願い';
  const data = dataRange.getValues();
  for (var i = 1; i < dataRange.getNumRows(); i++) {
    let name = data[i][nameIndex];  // 0行目はヘッダー情報のためスキップ(以下同様)
    let company = data[i][companyNameIndex];
    let email = data[i][emailIndex];
    let sendUrl = data[i][sendUrlIndex];
    
    // メール本文
    let body = `
    ${company}
    ${name}様
    
    お世話になっております。
    
    この度、${name}様の率直なお気持ち、ご意見を頂戴したく、
    アンケートにご協力頂きたく存じます。
    
    【アンケートURL】
    ${sendUrl}
    
    何卒宜しくお願い申し上げます。
    `
    
    try {
      GmailApp.sendEmail(email, subject, body, options={from: 'abc@gmail.com', bcc: 'xyz@gmail.com'});
      console.log('送信OK: ${name} ${company} ${email} ${sendUrl}');
    } catch (e) {
      console.log('送信NG: ${name} ${e.name} ${e.message}');
    }
  }
}

##コード詳細
###序盤

  • JavaScriptの関数定義はfunction 関数名(引数) { 処理 }
  • JavaScriptでは、データ型の定義しない
  • 変数も関数も小文字から始まり、ローワーキャメルケースで記述
  • 変数宣言はvar, let, constのいずれかから始まる
    • var・・・再宣言OK、再代入OK
    • let・・・再宣言NG、再代入OK
    • const・・・再宣言NG、再代入NG
  • GoogleスプレッドシートをGASで操作する際のざっくりとした段取りは以下のとおり
    1. Spreadsheetインスタンス生成
    2. SpreadsheetインスタンスからSheetインスタンス生成
    3. SheetインスタンスからRangeインスタンス生成
    4. RangeインスタンスからgetValuesメソッドで二次元配列生成
function sendQuestionnaire() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('シート1');
  const dataRange = sheet.getDataRange();

###中盤

  • JavaScriptのfor文はfor (var i = 1; i <= n; i++) { Trueの処理 };
  • Rangeインスタンスから行数/列数を取得するにはgetNumRowsメソッドと getNumColumnsメソッド
  • JavaScriptにはswitch文がある(構文は以下のとおり)
  • JavaScriptでフロー制御文中、何もしないときは;だけ書く
  • GASは行も列もインデックスが1から始まるが、二次元配列は0からなので厄介
  // 名前、会社名、E-mail、送信用URLの列数を取得(列数固定だと、列数が変わったときに機能しなくなるため)
  let nameIndex = 0;
  let companyNameIndex = 0;
  let emailIndex = 0;
  let sendUrlIndex = 0;
  for (var i = 1; i <= dataRange.getNumColumns(); i++) {
    switch (sheet.getRange(row=1, column=i).getValue()) {
      case '名前':
        nameIndex = i -1;  // 二次元配列のループは0から始まるため、列数を -1 する(以下同様)
      case '会社名':
        companyNameIndex = i -1; 
      case 'E-mail':
        emailIndex = i -1;
      case '送信URL':
        sendUrlIndex = i -1;
      default:
        ;
    }
  }

###終盤

  • 前述のとおり、GASでRangeインスタンスから値を二次元配列で取り出したいときはRange.getValuesメソッド
  • JavaScriptのテンプレート文字列は便利。Pythonのf文字列と似てる
  • GASでメール送信はGmailApp.sendEmailメソッド
    • 第一引数:宛先メールアドレス
    • 第二引数:件名
    • 第三引数:本文
    • 第四引数:オプション(下記以外にも添付ファイル等、色々ある模様)
      • fromオプション:エイリアスが複数ある場合に送信元を指定
      • Bccオプション:Bccを指定
  • Console.logメソッド書いておくと、Apps Scriptの画面でログ見れて非常に便利(デバッグ中の表示が遅いのはめっちゃイライラするけど)
  // E-mail送信
  const subject = 'アンケートご協力のお願い';
  const data = dataRange.getValues();
  for (var i = 1; i < dataRange.getNumRows(); i++) {
    let name = data[i][nameIndex];  // 0行目はヘッダー情報のためスキップ(以下同様)
    let company = data[i][companyNameIndex];
    let email = data[i][emailIndex];
    let sendUrl = data[i][sendUrlIndex];
    
    // メール本文
    let body = `
    ${company}
    ${name}様
    
    お世話になっております。
    
    この度、${name}様の率直なお気持ち、ご意見を頂戴したく、
    アンケートにご協力頂きたく存じます。
    
    【アンケートURL】
    ${sendUrl}
    
    何卒宜しくお願い申し上げます。
    `
    
    try {
      GmailApp.sendEmail(email, subject, body, options={from: 'abc@gmail.com', bcc: 'xyz@gmail.com'});
      console.log('送信OK: ${name} ${company} ${email} ${sendUrl}');
    } catch (e) {
      console.log('送信NG: ${name} ${e.name} ${e.message}');
    }
  }
}

#最後に
コートはこちらにもアップしました。
JavaScript & GAS初心者なので細かく書きました。
これを機に両言語とも避けないで使っていこうかな・・・と思います。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?