FIELD NOTES: 書を持って街へ出よう

合同会社フィールドワークス プログラマ兼代表のブログ

Google Apps Script でメールをタイマー送信する方法

メールの送信を予約して,決まった日時に送りたいことがあります。

そのようなことを実現するためのアプリケーションもあるようですが,常にPCの電源を入れておく必要があります。
一方,外部のASPサービス(「ステップメールサービス」など)も存在するようですが,有料であったり,無料であってもメール本文に広告が入ったりするので,気軽に使うことができません。

そこで,Google Apps Script を使ってメールのタイマー送信を実現してみました。

スプレッドシートの作成

まずは,Googleドキュメントでスプレッドシートを作成します。
シートを一つ追加し,「template」と「schedule」という名前に変更します。

templateシートには,2行目以降にメールの件名と,メール本文のテンプレートを記入します。
件名またはメール本文中の「${ … }」という文字列は,メール送信時に可変のパラメータに置き換えられます。

f:id:fet:20120117164330j:image:w640

scheduleシートには,送信予定日時,テンプレートの番号,宛名,メールアドレスを記入します。
templateシートの2行目のテンプレートがテンプレート番号1に対応します。

f:id:fet:20120117164331j:image:w640

スクリプトの作成

次にスクリプトを作成します。

「ツール/スクリプトエディタ…」メニューを選択し,コードを入力します。

変数BCCには,BCCの送信先を設定します。
不要であれば,空文字列にしてください。

/**
 * Send mail according to a schedule.
 * スケジュールに合わせて自動でメールを送信する。
 *
 * Created by: Field Works, LLC / 合同会社フィールドワークス
 * Reference: http://www.field-works.co.jp/
 * Date: 2012/01/17
 */

var BCC = 'admin@sample.com';

function format(templ, params) {
  return templ.replace(/\${(.*?)}/g, function($0, $1) {
    return (params[$1] && typeof(params[$1]) != "object") ?
      params[$1].toString() : JSON.stringify(params[$1]);
  });
}

// メール本文を取得する
function getMessage(ss, row, params) {
  var templ = ss.getSheetByName('template');
  var r = templ.getRange('A2:B99');
  var subject = r.getCell(row, 1).getValue();
  var body = r.getCell(row, 2).getValue();
  return {subject: format(subject, params), body: format(body, params)};
}

// メール送信
function sendEMail(to, subject, body, opt) {
  try {
    MailApp.sendEmail(to, subject, body, opt);
  } catch (e) {
    return {result: 'NG', message: e.message};
  }
  return {result: 'OK', message: ""};
}

// 送信スケジュールをチェックする
function checkSchedule() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var schedule = ss.getSheetByName('schedule');
  var r = schedule.getRange('A2:F999');
  var row = r.getNumRows();
  var now = (new Date()).getTime();
  for (var i = 1; i <= row; ++i) {
    // 「送信予定日時」が空ならデータの終わりと判断
    if (r.getCell(i, 1).getValue() == "") {
      break;
    }
    var tm = r.getCell(i, 1).getValue().getTime();
    var status = r.getCell(i, 5).getValue();
    if (status == "" && tm < now) {
      // メール送信
      var no = r.getCell(i, 2).getValue();
      var to =  r.getCell(i, 4).getValue();
      var params = {
        TO: r.getCell(i, 3).getValue(),
      };
      var msg = getMessage(ss, no, params);
      var ret = sendEMail(to, msg.subject, msg.body, {bcc: BCC});
      // 処理結果を書き込み
      r.getCell(i, 5).setValue(ret.result);
      r.getCell(i, 6).setValue(ret.message);
    }
  }
}

トリガーの設定

「トリガー/現在のスクリプトのトリガー…」メニューを選択して,タイマートリガーを設定します。
ここでは,15分毎にチェックするように設定しました。

f:id:fet:20120117164332p:image:w640

現在時刻が「送信予定日時」を超えるとメールを送信し,処理結果を「結果」欄に設定します。
メール送信処理中に例外が発生した場合は,「エラーメッセージ」欄に例外メッセージを残します。