📩

Googleフォームの入力をメールで通知したい

2022/06/11に公開

作ったものをペタリ

  • Google フォームに入力があったことを任意の関係者にお知らせ
  • 関係者が Gmail アカウントを持っている必要はない
  • フォームの項目は記事用に省略
    • 基本はテキスト回答(短文回答段落回答)を想定
    • 他の回答形式(ラジオボタンセレクトボックスなど)の動作確認はしてない
// Googleフォームに入力があった場合に、関係者に通知する

// フォームの項目
// 1. 承諾 -> confirm(これはメール本文には不要)
// 2. 申請者の名前 -> name
// 3. 申請者の所属 -> affiliation

function onFormSubmit(e) {
  // フォームのメタデータを取得
  // 申請時刻
  const timestamp = e.response.getTimestamp();
  // 収集したアドレス
  const respondent = e.response.getRespondentEmail();

  // フォームの回答を取得
  const itemResponses = e.response.getItemResponses();
  const values = itemResponses.map(function (itemResponse) {
    return itemResponse.getResponse();
  });

  const confirm = values[0];
  const name = values[1];
  const affiliation = values[2];

  // メール本文を作成する
  const body = `
Googleフォームに申請がありました。

----------------------------------------
# 申請日
${timestamp}

# 申請者
${name}${affiliation})
----------------------------------------
`;

  // メールの件名を作成する
  const subject = `Googleフォーム申請(${name}`;

  Logger.log(subject);
  Logger.log(body);

  // メールの下書きを作成する
  const to = "addr1@example.com,addr2@example.com,addr3@example.com";
  const draft = GmailApp.createDraft(to, subject, body, { name: "Your name" });
  // メールを送信する
  draft.send();
}

パーツに分けて説明する

  1. フォーム申請時の関数を作成する
  2. 申請時刻を取得する
  3. 収集したアドレスを取得する
  4. フォームの回答を取得する
  5. メールの本文を作成する
  6. 関係者にメールを送信する

フォーム申請時の関数を作成する

function onFormSubmit(e) {
  ...
}
  • 任意の関数名でいいのかもしれないが、onFormSubmitとしている例が多いのでそれに倣った
  • フォームに申請があるとeにフォームに関するデータが詰め込まれる(っぽい)
  • このあと、とくに e.responseFormResponseクラスのオブジェクト)からデータを取りだしていく

https://developers.google.com/apps-script/reference/forms/form-response

申請時刻を取得する

申請時刻を取得
const timestamp = e.response.getTimestamp();
  • 返り値は Date オブジェクト
  • 本文に表示するときには toDateString() などで整えてもいいかもしれない

https://developers.google.com/apps-script/reference/forms/form-response#getTimestamp()

申請者から収集したアドレスを取得する

収集したアドレスを取得
const respondent = e.response.getRespondentEmail();
  • フォームで メールアドレスを収集する 設定にしている場合
  • 申請者本人には、Google フォームから回答のコピーを送るように設定してある
    • 今回の通知メールの"関係者"には含めない

https://developers.google.com/apps-script/reference/forms/form-response#getRespondentEmail()

フォームの回答を取得する

フォームの回答を取得
const itemResponses = e.response.getItemResponses();
const values = itemResponses.map(function (itemResponse) {
  return itemResponse.getResponse();
});
  • フォームの項目にしたがって、回答をvaluesに配列として詰め込んでいる
    • 以前は e.values という変数があったようだが、いまはUndefinedとなる
    • なので、それっぽい配列 values を自分で作成している
  • itemResponses(複数形) と itemResponse(単数形) の使い分け/スペルミスに注意する
  • GAS(or JS)の書き方をいまいち分かってないが、.mapしている部分はPythonでいうリスト内包表記と同じようなことをする書き方だと思っている
リスト内包表記
values = [itemResponse.getResponse() for itemResponse in e.response.itemResponses()]

https://developers.google.com/apps-script/reference/forms/form-response#getItemResponses()

https://developers.google.com/apps-script/reference/forms/item-response#getResponse()

メール本文を作成する

メール本文を作成
const confirm = values[0];
const name = values[1];
const affiliation = values[2];

// メール本文を作成する
const body = `
Googleフォームに申請がありました。

----------------------------------------
# 申請日
${timestamp}

# 申請者
${name}${affiliation})
----------------------------------------
`;
  • valueに詰め込んだ入力内容を分かりやすい変数名に代入しなおす
  • メールの本文はテンプレートリテラル(テンプレート文字列)を使って作成する
    • ${変数名} と書くことで変数を代入することができる
    • 思い通りの本文を作成することができるので便利
    • 改行やインデントもそのまま反映されるので注意

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Template_literals

関係者にメールを送信する

メールを作成
// 件名を作成
const subject = `Googleフォーム申請(${name}`;
// 宛先を作成
const to = "addr1@example.com,addr2@example.com,addr3@example.com";
// 下書き作成
const draft = GmailApp.createDraft(to, subject, body, { name: "Your name" });
// メール送信
draft.send();
  • 件名を作成 : テンプレートリテラルを使って申請者名を追加
  • 宛先を作成 : 関係者のアドレスを直書き。カンマ区切りで複数の宛先を設定できる
  • 下書き作成 : createDraftのオプションで差出人の名前を設定
  • メール送信 : 1 日に送ることができるメール数の制限に注意

https://developers.google.com/apps-script/reference/gmail/gmail-app#createDraft(String,String,String,Object)

リファレンス

https://developers.google.com/apps-script/reference/forms

トリガーの設定

  • フォームに入力があった際に onFormSubmitが実行されるようにトリガーを設定する

設定項目

  • 実行する関数を選択 : onFormSubmit
  • デプロイ時に実行 : Head(ここはたぶん変更できない)
  • イベントのソースを選択 : フォームから
  • イベントの種類を選択 : フォーム送信時
  • エラー通知設定 : 毎日通知を受け取る(好みで選択)

テスト時の注意

  • フォームを入力して送信しないと動作テストができないので、結構手間がかかった
  • 内容が空でも送ることができる簡単なテスト用フォームを用意して、API の確認をしながら動作テストをしていたら、そのフォームにアクセスできなくなってしまった
  • Google の方でスパムっぽいと思われてしまったのかもしれない。次回からは気をつけようと思った

おまけ

  • フォーム入力とは関係なく、メール送信の部分だけのテスト用
function testMail() {
  // メール送信テストするための関数

  // 入力値のダミーを用意する
  const name = "申請者の名前";
  const affiliation = "申請者の所属";

  // メール本文を作成する
  const body = `
【テスト】Googleフォームに入力がありました。
----------------------------------------
# 申請者
${name}${affiliation})
----------------------------------------
`;

  // メールの件名を作成する
  const subject = `【テスト中】Googleフォーム申請(${name}`;
  console.log(subject);
  console.log(body);

  // メールの下書きを作成する
  const to = "addr1@example.com,addr2@example.com";
  const draft = GmailApp.createDraft(to, subject, body, { name: "Your Name" });
  Logger.log(draft);
  draft.send();
}

Discussion