今回は、Googleフォーム →(送信)→ GAS →(自動返信)→ 送信者 の仕組みを作ります。面倒な定型返信や受付確認は、フォーム送信のタイミングで自動化してしまいましょう。
Contents
全体の流れ
- フォームに「メールアドレス」質問を追加(必須)
- フォームの「スクリプトエディタ」を開く(フォームに紐づくGAS)
- 自動返信スクリプト(
onFormSubmit(e))を記述 - 「トリガー」で フォーム送信時 を選び、インストール型トリガーを設定
- テスト送信 → 受信確認
まずは動く!最小コード(プレーンテキスト返信)
フォームの「スクリプトエディタ」で下記を貼り付け、保存します。フォームの 1問目をメールアドレス と想定しています。
function onFormSubmit(e) {
// 回答データを取得
const itemResponses = e.response.getItemResponses();
const email = itemResponses[0].getResponse(); // 1問目=メールアドレス
// 返信本文(プレーンテキスト)
const subject = "【自動返信】お問い合わせありがとうございます";
const body = [
"この度はお問い合わせありがとうございます。",
"担当者が内容を確認し、折り返しご連絡いたします。",
"",
"――",
"自動送信:このメールへ直接のご返信はご遠慮ください。"
].join("\n");
// 送信
GmailApp.sendEmail(email, subject, body);
}
トリガー設定:エディタ左の「時計アイコン」→「トリガーを追加」→ onFormSubmit を選択 → イベントのソース「フォームから」、イベントの種類「フォーム送信時」。初回は権限承認が必要です。
実用版:差し込み+HTMLメール+ログ保存
届いた回答を差し込んで、読みやすいHTMLメールで返信します。あわせてスプレッドシート(回答先)に「返信済み」のログを残すと運用が楽になります。
/**
* フォーム送信時に自動返信(HTML)&スプレッドシートへログ
* 前提:
* - Q1: メールアドレス(必須)
* - Q2: お名前
* - Q3: お問い合わせ内容
* - フォームはスプレッドシートへリンク済み
*/
function onFormSubmit(e) {
const res = e.response;
const items = res.getItemResponses();
// タイトル → 回答 のマップを作る(タイトル名で参照できるように)
const data = {};
items.forEach(ir => data[ir.getItem().getTitle()] = ir.getResponse());
// 項目名はフォームの実際のタイトルに合わせてください
const email = data["メールアドレス"]; // 必須
const name = data["お名前"] || "お客様";
const content = data["お問い合わせ内容"] || "";
// HTML本文
const subject = "【自動返信】お問い合わせを受け付けました";
const htmlBody = [
"<p>" + name + " 様</p>",
"<p>この度はお問い合わせありがとうございます。以下の内容で受け付けました。</p>",
"<hr>",
"<p><strong>お問い合わせ内容</strong><br>" + safeHtml(content) + "</p>",
"<hr>",
"<p>担当者より通常1〜2営業日以内にご連絡いたします。</p>",
"<p>※このメールは自動送信です。</p>"
].join("");
// 送信(プレーン本文は空でもOK。htmlBodyを使用)
GmailApp.sendEmail(email, subject, "", {
htmlBody: htmlBody,
name: "自動返信システム"
});
// 回答スプレッドシートに「返信済み」ログを残す(最終行に対して)
const sheet = getLinkedResponseSheet_();
if (sheet) {
const lastRow = sheet.getLastRow();
const headers = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0];
// 「返信済み」列がなければ作成
let col = headers.indexOf("返信済み") + 1;
if (col === 0) {
col = headers.length + 1;
sheet.getRange(1, col).setValue("返信済み");
}
sheet.getRange(lastRow, col).setValue(new Date()); // タイムスタンプを記録
}
}
/** HTMLに差し込むテキストを簡易エスケープ */
function safeHtml(text) {
return String(text).replace(/[&<>"]/g, s => (
{ "&":"&", "<":"<", ">":">", '"':""" }[s]
));
}
/** フォームとリンクされた回答スプレッドシートを取得 */
function getLinkedResponseSheet_() {
try {
const form = FormApp.getActiveForm();
const url = form.getDestinationId(); // 回答先スプレッドシートのID
if (!url) return null;
const ss = SpreadsheetApp.openById(url);
return ss.getSheets()[0]; // 回答先の先頭シート
} catch (e) {
Logger.log(e);
return null;
}
}
ポイント:フォームの「質問タイトル」をキーにして差し込むため、フォーム側の文言を変更したらスクリプトのキー名も合わせましょう。HTMLメールは htmlBody オプションで送れます。
テンプレート化:本文・差出人名・フッターを統一管理
運用時は本文やフッターをコードから切り離すと便利です。GASのプロパティサービスを使って、編集を楽にしましょう(「プロジェクトのプロパティ」→「スクリプトのプロパティ」)。
function onFormSubmit(e) {
const props = PropertiesService.getScriptProperties();
const SENDER_NAME = props.getProperty("SENDER_NAME") || "自動返信システム";
const FOOTER = props.getProperty("MAIL_FOOTER") || "\n――\n自動送信メール";
const items = e.response.getItemResponses();
const data = {};
items.forEach(ir => data[ir.getItem().getTitle()] = ir.getResponse());
const email = data["メールアドレス"];
const name = data["お名前"] || "お客様";
const content = data["お問い合わせ内容"] || "";
const subject = "【自動返信】お問い合わせありがとうございます";
const body = [
name + " 様",
"",
"以下の内容で受け付けました。",
"",
"【お問い合わせ内容】",
content,
"",
FOOTER
].join("\n");
GmailApp.sendEmail(email, subject, body, { name: SENDER_NAME });
}
文面変更はプロパティの値を書き換えるだけ。運用メンバーがコードに触れずに更新できます。
よくある詰まりポイント&対策
- トリガーが動かない:「フォーム送信時」のインストール型トリガーを設定しているか確認(単なる
onSubmitの関数名だけでは動きません)。 - メールが届かない:迷惑メール判定/宛先入力ミス。テストは自分のアドレスで。
- 差し込みが空欄:フォームの質問タイトル変更が原因。スクリプトのキー名を合わせる。
- 二重送信を防ぎたい:回答ID(
e.response.getId())をシートに保存し、重複時はスキップ。 - 情報保護:個人情報は本文に過度に含めない。長文は要約して返信。
まとめ
GoogleフォームとGASの連携で、受付確認・自動返信・運用ログまでまとめて自動化できました。これだけで問い合わせ対応の手間が大きく減ります。次回はトリガーで完全自動運用へ進みます。
