
どーも!
今回は前々から気になっていたのですが、GASを使ってみようと思います!
Google App Scriptの略ですが、Google系のサービスでちょっとしたプログラムを書くことで色々と便利にすることができる...!
てきな印象だと思っています...!
今回はGoogleFormという、汎用的なアンケートを取る機能に対して、アンケートの項目にメールアドレスを追加し、そのメールアドレスに対して、入力された内容を確認のため送信する...といったことを試してみようと思います!
確か...GoogleForm自体の機能として内容確認のメールを送る...といった機能はあった気もしますが...
あくまでGASがどんなものなのかな〜?っていうのを知るために試した...といった感じで試してみようと思います!
目次
グーグルフォームの入力内容を入力されたアドレスにメールで送信する
最初に、今回目指すゴールを提示しておきます。
例えば...
以下のようなグーグルフォームを作り、その項目の一つにメールアドレスを用意します。

ここにメールアドレスを入力してもらうようにしているので、そのメールアドレスに対してメールを送信します。
メールアドレスのバリデーション等はいったんなしで考えます。
ではやっていきましょう!
GoogleFormを用意する
さて、まずはグーグルフォームを作ります。
実は筆者もあまり触ったことないんですよねw
回答する側にはなるんですけどね。
では作っていきます!
まず最初にご自身のGoogleアカウントでgoogle ドライブを開きます。
Chromeをお使いの人は以下の右上のツールバーにあるアイコンから楽にいけます。

chromeでない場合は以下からログイン等すればいけるかと思います。
ドライブを開いたら、任意のフォルダにて右クリックでGoogleフォームを作ります。
目印としては紫色のアイコンのやつですね。

さて、新規作成すると以下のような画面がでてきます。

筆者は初めて使ったのでへぇ〜!こんな楽に作れるんだ〜wって感じでした...!
簡単に説明しておくと、上記の形に作ってもらえれば大丈夫なのですが....

お名前は記述式にして入力必須に。
また、新規項目は右側にある+ボタンから可能です。

追加したら、メールアドレスも記述式にしておきます。
こちらも入力必須でもいいんですが、今回は必須ではない形にしています。
一通りできたら、右上の目のマークからプレビューと動作確認ができるので、試してみましょう。

プレビューボタンを開くと新しいタブにいつも回答をする人のために表示される画面がでてくると思います。
適当に値を入力して送信してみましょう。

適当に入力して送信をすると...

こんな画面になります。
そして、下の編集タブに戻って上部の回答タブを開きます。

すると、先程回答した回答内容が確認できるはずです。

これで、フォームの準備はOKです。
最後に、フォームの値をプログラムで使用するため、いったんスプレッドシートに書き込まれるようにします。
これも非常に簡単で、先程の回答画面の右上あたりにあるスプレッドシートマーク(緑のマーク)からボタン一つで作ることができます。


作成すると...?

上記のように入力されている内容がリストされているスプレッドシートがでてくると思います。
googleフォームから改めて別の回答をして、それを送信すると....?

このように、新規で追加されるようになります。
これで前準備は完璧です!
では次にスクリプトを書いていきましょう!
スクリプトを用意する
さて、ではここからが本番!
先程作成したスプレッドシートのツールから、スクリプトエディタを開きます。
(ドライブの画面から右クリックでスクリプトの作成も可能ですが、後ほど説明するスプレッドシートとのトリガー設定ができないため、スプレッドシートから作成してください。)

それをクリックすると、以下のようなスクリプト編集画面がでてきます。
まずはタイトルの無題のプロジェクトをクリックして名前を変えておきます。

そしたら、以下をコピペします。
function myFunction() {
console.log('test')
}
コピペしたら、実行を押しましょう。

問題なければ以下のようにログがでてくるはずです。

先程追加したのはJSで書いた、実行されたら"test"と表示するプログラムになっています。
それを試しに実行したわけですね。
ここに、フォームの値を取得し、その値から入力された内容を取得し、メールを送信...といった具合のことをこれからやっていきます。
では、フォームの値を取得しましょう!
Googleフォームに入力された値を取得する
ではやっていきましょう!
まず最初にフォームに入力された情報を取得する部分を書きます。
フォームに入力された後、スプレッドシートへ転記するため、その内容が書き込まれたら...関数を実行する...といった具合にやっていきます。
まず、スクリプトを以下のように書き換えてください。
今回は返信をする...といった意味合いがあるので、sendReplyという関数名にしています。
function sendReply(e) {
console.log(e)
}
書き換えたら、command + sで保存します。(macの場合)
保存したら、画面左からトリガーを選択します。

トリガーを選択したら、以下のような画面がでてくると思うので、その右下にある青い"トリガーを追加"ボタンを押します。

トリガーとは、関数がどのタイミングで(スプレッドシートが更新されたタイミング....等)その関数を実行するのか?を設定するための項目です。

実行する関数は先ほど書いたプログラムの関数名になっていればOKです。
また、デプロイはいったん気にしないでください。
イベントのソースとイベントの種類ですが、"スプレッドシート"が"更新"されたら...
といった具合に、"ソース"に対する"操作"で関数の実行を行うため、どんなソースが操作されたら?と言うのを指定するのがイベントのソース、どんな操作をされたら?というのを指定するのがイベントの種類になっています。
今回は以下のように設定しました。

Googleフォームの送信によって、スプレッドシートに追加されたタイミングでsendReplyメソッドを実行する...といった具合のトリガーです。
イベントの種類選択時に"編集時"もあり、それでもいいのでは?と思うかもしれません。
ただ、その場合、フォーム回答結果のスプレッドシートをちょっとでも人手で編集してしまったら関数が走ってしまいます。(入力内容の修正等...)
プログラム側で処理できないこともありませんが、用意されている機能を使う方が無難でしょう。
上記設定ができたら保存します。
テスト用に作成したアカウントなので、メアドも晒しちゃうんですが...!
以下のようにアカウント選択画面がでてくると思います。

これは、先程ドライブにフォームを作成したアカウントと同じ物を選択し、ログインします。
すると、以下のような画面がでてきます。

これは、このアプリというのが先ほど書いたプログラムのことで、プログラムがあなたのGoogleアカウントのリソース(アンケートの回答フォームのスプレッドシート)へアクセスしてもいいですか...?
というのを確認しているためでてきています。
自分で作ったプログラムでもアクセス確認が必要なんですね。
では、許可していきましょう。
左下の詳細から、追加の文章を開き...?

下の方にある、(安全でないページ)へに移動します。(念のため、デベロッパーのメールアドレスが自分のものかは確認しておきましょう)
すると、プログラムに対して、こういうアクセスを許しますよ?といった文章がでるため、許可します。

無事完了すればトリガーが追加されるはずです。

では、左からエディタを選択し、再度メールフォームに値を入力、送信してみましょう。
送信済みアンケートフォームから、別の回答を送信等で楽に再送信ができると思います。


適当に入れて送信。
送信したら、画面左から"実行数"のタブを選択します。

実行数を押すと、以下のように今までの実行ログが確認できます。
種類が"エディタ"になってるのはエディタで更新した際に動いたログ、トリガーはトリガーで実行されたログです。

先程トリガー実行しているはずなので、このトリガーの方を選択します。
すると...
うじゃうじゃ〜っと英語がでてくると思います。
下の方へスクロールすると先程入力した内容があればOKです。

これは先程のプログラムで...以下のようなものに書き換えました。
function sendReply(e) {
console.log(e)
}
これは、トリガーが実行された際、そのコンテンツを含んだ情報というのを"e"と言う値として取得している...と言うことです。
eは変数といって、変数の中に先程のうじゃうじゃーとあったさまざまな情報を含んでいるわけです。
console.log(e)というのでその中身を出す...と言う処理を行っているため、先程のログにでていたんですね。
では、試しに以下のように書き換えて再度フォームを送信しましょう。
function sendReply(e) {
console.log(e.values)
}
すると...?

上記のように入力された日付、内容のみ抽出できました!
先程のうじゃうじゃーとあった画像の一番下の行だけみていただきたいのですが...
以下のようになっていますね。
values:[ '2021/02/07 14:23:36', 'テスト三郎', 'test@example.com' ] }
valuesとして、これら三つのデータを持っているため、それだけ欲しい場合は"e.values"とすれば取り出すことができます。
rangeなどはどこからアンケート内容が始まっているのか?とか、どれくらい項目数があるのか?とかあったりしますね。
それらも、"e.range"といった形で取得できますが、今回は使わないので、アンケートフォームの入力内容は"e.values"で値が取れるんだ...!
程度でいいかと思います。
値の取得ができたので、メール送信を行っていきましょう...!
メールを送信する
さて、それではメールを送信しましょう!
まずは以下のように関数の中身を書き換えてください。
function sendReply(e) {
const title = "【ご返信】GASテストフォームから"
GmailApp.sendEmail(e.values[2], title, e.values[1])
}
そして、一度エディタから実行します。

すると...以下のような画面が出てくると思います。
これは、先程と一緒なのですが、アプリケーションが今度はメール送信をしてもいいかどうか?といった、権限を承認する必要があります。
先程はスプレッドシートへのアクセスでしたが、今度はメール機能の承認というわけですね。

権限を確認を押すと...

先程と同一のアカウント選択画面がでてきます。
これ以降は先程と同一手順で大丈夫です。
最終的に許可できたら、プログラムが実行され、以下のログがでます。

これは、トリガーで実行しなかった(エディタで実行した)ため、本来入ってくるべきフォームの入力内容が入っていないことによるエラーです。
本来なら値が入ってこなかった場合は〜といった処理も書いた方がいいと思いますが、今回は割愛します。
では、これでアプリケーションがメール送信もできるはずなので、再度フォームを送信して、先程のテストアカウントに対してメールを送信してみます。
フォームを送信すると...?

メールが届きました!
タイトルが入って、そのコンテンツにはフォームで入力した名前がでています。(たかぽん)
これで、いったんメール送信ができました!
試しに...
yahoomailの方にも送ってみましたが、ちゃんととどきました。


最後にもう少し文面をマシにしてから終わりたいと思います。
簡単に解説しておくと....
function sendReply(e) {
const title = "【ご返信】GASテストフォームから"
GmailApp.sendEmail(e.values[2], title, e.values[1])
}
上記で、title等定数として、"【ご返信】GASテストフォームから"を設定しました。
そして、GmailApp.sendEmailと言うのが、GASで提供されているメール送信のためのAPI(機能的なものです)になっています。
そのAPiを使うことで、メール送信ができるようになります。
カンマ","区切りで、引数(渡す値)を三つ与え、
GmailApp.sendEmail(宛先のメールアドレス, メールのタイトル, メール本文)
といった具合に使うことができます。
まともな文面を整える
最後に文面を整えましょう。
大きく変更しましたが、以下コピペしてお試しください...!
function sendReply(e) {
const answeredDate = e.values[0] // 回答された日時
const answeredName = e.values[1] // 回答されたお名前
const answeredEmail = e.values[2] // 回答されたEmail
const ownName = 'たかぽん' // こちらの名前
const refUrl = 'https://tektektech.com/' // 紹介URL
const title = "【ご返信】GASテストフォームから"
const body = `
${answeredName} 様
この度はアンケート"${title}"にご回答いただきありがとうございます。
もしよろしければ以下もご覧ください。
てくてくテック: ${refUrl}
これからもどうぞ、よろしくお願いいたします。
${ownName} より
`
GmailApp.sendEmail(answeredEmail, title, body)
}

上記を送ると...?
以下のようなメッセージが送信されます。

さて、最後に簡単に解説だけ...
以下にて、e.values等の情報や、そのほかの本文に使いたいものをわかりやすいように変数に入れ、扱えるようにしています。
const answeredDate = e.values[0] // 回答された日時
const answeredName = e.values[1] // 回答されたお名前
const answeredEmail = e.values[2] // 回答されたEmail
const ownName = 'たかぽん' // こちらの名前
const refUrl = 'https://tektektech.com/' // 紹介URL
const title = "【ご返信】GASテストフォームから"
例えば、今までは"e.values[0]"として別の場所で使う場合、その値が何を指しているのか?フォームのアンケート項目を見に行かなければいまいちわかりづらいですよね?
それに対して、anseredDateという定数に入れることで、回答回答日時なんだな!ってことがわかりやすくなります。
ちなみに、じゃフォームのどの値が何番なんだよ!って思うんですが...
先ほど確認した情報を見てみてください。
values:[ '2021/02/07 14:23:36', 'テスト三郎', 'test@example.com' ]
こうなっていましたね。
カンマ区切りで左から順番にvalues[0](=2021/02/07 14:23:36), values[1](=テスト三郎), values[2]...となっています。
プログラムの世界ではこのデータのことを配列と呼び、その添え字は0から始まるんですね。(非エンジニアからすると違和感でしょうが、そうなってるんです...orz)
また、ownNameなどは、自分の氏名や社名を入れる値という意味をもたせて、定数化しています。
後ほど本文に埋め込んでいくのですが、そのまま本文に"たかぽん"と記載してもいいけど、それだと今後担当者が変わったりした場合に本文をみにいかなければいけなくなってしまいます。
もしくは、複数箇所で使う場合はこの定数だけ修正すれば全部の箇所が変わる...といった利点もあったりします。
本文中で繰り返し出現するような値や、頻繁に変更する予定...の値などは定数化しておくと運用が楽になるでしょう。
ちなみに、"//"の後ろに書いてあるものはコメントアウトといわれていて、自由な文章をかけます。
普通、"//"なしで日本語なんてかいたらエラーになってしまいますが、"//"でメモを残せるようになっています。
では、次に行きます。
const body = `
${answeredName} 様
この度はアンケート"${title}"にご回答いただきありがとうございます。
もしよろしければ以下もご覧ください。
てくてくテック: ${refUrl}
これからもどうぞ、よろしくお願いいたします。
${ownName} より
`
こちらが本文になります。
bodyという定数に値を入れていますね。
そして、" ` "(バッククォート)を使って文章を挟んであげると、それがそのまま文章として扱うことができます。
その中で、${定数・変数名}とすることで、定数や変数をその中へ埋め込むこともできるんです。
※とても似ている" ' "(シングルクォート)だと、${定数・変数名}としても変数ではなく文字として認識されてしまうためご注意ください。
改行を入れたい場合は改行をいれればそのまま反映されるため、大抵のことは似たようにすれば実現できるかと思います。
最後は、回答されたメールアドレスへ、titleの中身をタイトルとして、bodyの中身を本文としてメールを送る...といった感じです。
GmailApp.sendEmail(answeredEmail, title, body)
定数に名前をつけたことでわかりやすくなったかと思います。
answeredEmailなどは僕が勝手に考えた名前なので、ご自分のわかりやすい名前にしてもらっても大丈夫です。
これで、あとはフォームを共有すれば一通り完成です!
長くなってしまいましたが以上で終わります!
最後に、今回のプログラムも完璧ではないので、留意点だけお伝えしておきます。
今回の実装に対する留意点
さて、メールが送信できることは確認できたかと思います。
ただ、メールのバリデーション(正しいか確認)はおこなていないため、確実にメールを送信したい...!
といった需要がある場合は今夏の実装だけでは心許ないかなと思います。
例えば...最悪届かなくてもいいけど、フォーム回答してくれたユーザーに簡単な紹介くらい送っておきたい...程度であれば十分かなと思います。
気になる点としては...
- ユーザーがメールアドレスを間違えて入力した場合届かない
- 意図的に他人のメールアドレスを入力された場合も送信されてしまう(その後のケア等をしてない)
等は問題になりうるかなぁと思っています。
まとめ
さて、色々とお伝えしてきましたが、より自分の好きにカスタマイズしたい場合は、Javascriptや、APIに関する知識をつける必要がありそうです。
GASのAPI例として今回使ったSendEmailは以下にあります(日本語版はなさそうですね....)
軽くみた感じnoreply等のオプション(noreply@~~~といったアドレスからの送信になり、返信できなくなる)等もできそうです。
また、先程プログラムを書き換えて本文の形式を修正したり、定数に入れたりしましたが、それに関してはJavaScriptで調べると色々とでてくるかと思います。
GASではプログラミング言語のJavaScriptを使用しているため、それと同じ方法で文章を書いたりすることができるんですね。
そのため、JavaScriptの勉強をすればある程度GASでいろいろなことをすることができるようになると思います!
それでわ!長くなりましたが、今回は以上です!