キャンペーンの案内やイベントの告知を、スプレッドシートの宛先リストから一件ずつコピーして送っている場合、件数が増えるほど手間も送信漏れのリスクも大きくなります。
この記事では、Google Apps Scriptで宛先リストへ一斉にメールを送る仕組みを、宛名の差し込みと送信記録の管理、送信上限を超えないための対策まで整理しています。
完成イメージと送信記録の仕組み
完成すると、スプレッドシートに並んだ宛先へ1通ずつ宛名入りのメールが送られ、送信済みの行には印と日時が自動で記録される仕組みです。
宛先リストを1行ずつ読み込み、まだ送信していない行だけを対象にメールを送信し、送り終えた行に「済」の印と送信日時を書き込みます。
この印があるため、同じスクリプトを何度実行しても、すでに送ったメールが二重に送られることはありません。
受信メールをスプレッドシートに残す仕組みと組み合わせれば、問い合わせ対応の記録も自動化できます。

手順
宛先リストの準備からトリガー設定まで、4つのステップで完成します。
Step1. 宛先リストの列構成を準備する
新しいスプレッドシートを用意し、A列にメールアドレス、B列に宛名、C列に送信済みフラグ、D列に送信日時という順で見出しを入れます。
2行目以降に送りたい相手の情報を入力し、C列とD列は空欄にしておいてください。
画面下部のシート見出し(初期状態では「シート1」)をダブルクリックし、名前を「送信リスト」に変更しておいてください。
この列構成とシート名が、次のコードがそのまま読み込む前提になります。
Step2. コードを貼り付ける(コード全文)
スプレッドシート上部のメニューから拡張機能を開き、Apps Scriptを選んでスクリプトエディタを立ち上げます。
表示されているコードを全て消し、次のコードを貼り付けてください。
function sendBulkEmails() {
const sheetName = '送信リスト'; // ★ここを変える: 宛先リストのシート名
const mailSubject = 'キャンペーンのご案内'; // ★ここを変える: 件名
const mailBodyTemplate = '{{名前}}様\n\nいつもお世話になっております。\nここに本文を記入します。'; // ★ここを変える: 本文({{名前}}が宛名に置き換わる)
const testModeOnly = false; // ★ここを変える: trueにすると未送信の先頭1件だけ送って停止する
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
if (!sheet) {
throw new Error(`シート「${sheetName}」が見つかりません`);
}
const lastRow = sheet.getLastRow();
if (lastRow < 2) {
return;
}
const listRange = sheet.getRange(2, 1, lastRow - 1, 4);
const rows = listRange.getValues();
let remainingQuota = MailApp.getRemainingDailyQuota();
for (let i = 0; i < rows.length; i++) {
const emailAddress = rows[i][0];
const recipientName = rows[i][1];
const sentFlag = rows[i][2];
if (emailAddress === '' || sentFlag === '済') {
continue;
}
if (remainingQuota <= 0) {
break;
}
const personalizedBody = mailBodyTemplate.replace(/{{名前}}/g, recipientName);
GmailApp.sendEmail(emailAddress, mailSubject, personalizedBody);
remainingQuota--;
sheet.getRange(i + 2, 3).setValue('済');
sheet.getRange(i + 2, 4).setValue(new Date());
if (testModeOnly) {
break;
}
}
} mailBodyTemplate に含めた {{名前}} の部分が、B列の宛名に置き換わってから送信される仕組みです。
remainingQuota は残りの送信可能件数を表す変数で、上限に達した時点でループを止め、続きは次回の実行に持ち越します。
送信が終わった行にはC列に「済」、D列に送信日時が書き込まれるため、途中で止まっても再実行時に同じ相手へ送り直す心配はありません。
Step3. 1件だけ送信してテストする
いきなり全件へ送る前に、コード内の testModeOnly を true に書き換えて保存します。
この状態で sendBulkEmails を実行すると、未送信の先頭1件だけにメールが送られ、C列とD列に記録が入ったところで処理が止まります。
自分のアドレスを1行目に入れておいて届く内容を確認し、問題がなければ testModeOnly を false に戻してください。
Step4. トリガーを設定して自動化する
スクリプトエディタの左側にある時計マークの「トリガー」を開き、右下の「トリガーを追加」から設定します。
実行する関数は sendBulkEmails、イベントのソースは時間主導型、種類は分ベースまたは時間ベースのタイマーを選び、実行間隔を指定して保存します。
件数が多く1回で送り切れない場合も、この定期実行によって残りの行は翌日以降に自動で送信される仕組みです。
Gmailの送信上限と分割送信の注意
Google Apps Scriptから GmailApp や MailApp でメールを送る場合、1日に送れる件数には上限があります。
この上限はGoogleアカウントの種類によって異なり、下の表のとおりです。
| アカウントの種類 | 1日あたりの送信可能件数 |
|---|---|
| 個人のGoogleアカウント | 100件 |
| Google Workspaceアカウント | 1,500件 |
出典:Google「Apps Script quotas for Google services」
GmailApp.sendEmail と MailApp.sendEmail は同じ日次上限を共有するため、どちらの命令を使っても上限そのものは変わりません。
宛先リストがこの件数を超える場合、Step4のトリガーが上限到達時点で処理を止め、翌日以降の実行で残りを自動的に送り切る形になります。
急ぎで全件を送り切りたい場合、宛先リストを複数のシートに分けて別々のGoogleアカウントから実行する方法もあります。
ただし運用が複雑になるため、まずは1つのアカウントで上限まで送り、残りを翌日に回す形から始めるのが無難です。
期限が近づいた相手にだけ絞って送りたい場合は、条件付きの通知の作り方も参考になります。

どの業務から自動化に着手すべきか迷う場合は、判断基準を別記事で整理しています。

Google Apps Scriptでの一斉メール送信について相談してみませんか?
「宛先リストが数千件あり上限内で送り切れるか分からない」「宛名以外にも会社名や金額を差し込みたい」「社内にGoogle Apps Scriptを設計できる人材がいない」
少しでもお心当たりがあれば、お気軽にご相談ください。
現在、Google Apps Scriptを使った業務自動化のお悩みをお伺いする 無料の個別相談 を実施しています。
よくある質問
Q. 宛名以外の項目も差し込みできますか?
できます。
宛先リストに会社名や金額などの列を追加し、mailBodyTemplate に {{会社名}} のようなプレースホルダーを増やしてください。
対応する replace の処理を1行ずつ追加すれば、差し込む項目を増やせます。
Q. HTMLメールとして装飾したメールを送れますか?
送れます。
GmailApp.sendEmail の第4引数に { htmlBody: htmlContent } を渡す形にすれば、太字や色付きのHTMLメールとして送信できる仕組みです。
Q. 送信済みの記録を誤って消してしまった場合はどうなりますか?
C列の「済」を消した状態で sendBulkEmails を実行すると、その行は未送信として扱われ、再度メールが送られます。
記録列は手動で編集しない運用にするか、編集前にシートのコピーを取っておくと安全です。
Q. 上限に達したかどうかは実行前に確認できますか?
確認できます。
スクリプトエディタで別途 Logger.log(MailApp.getRemainingDailyQuota()) を実行すれば、その時点で残っている送信可能件数がログに表示されます。