Google Apps Scriptでフォームメールを送る【GAS】
Google Formはフォームとしてページを表示するだけでなく、メールの中にフォームを埋め込んで送ることが可能です。しかし、FormAppには、フォームを作成するメソッドは合っても、Google Apps Scriptからそれを埋め込んだメールを送るメソッドが存在しません。そのため、メールで送るには、1人ずつ手動で、Google Form上で作業をしなければならない。
そこでGoogle Formを使わずに、フォームメールを作り、データをスプレッドシートに直接格納することはできないだろうか?と考えたのが今回の手法です。尚、Google Formのフォームメールも、今回の手法もスマートフォンのGMailアプリ上では入力が出来ません(セキュリティの関係上)。PC上では問題なく入力が可能です。
図:きちんとValidationも働く
目次
今回使用するスプレッドシート類
GMail上では、JavaScriptは動きませんが、CSSで装飾する事は可能です。また、今回、Submit先は別に用意したdoPostの受け皿のURLを指定しているので、そちらで値を取得することが可能です。
ソースコード
GAS側コード
var sheetid = "ここに書き込み先スプレッドシートのIDを入力する";
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu("Apps Script")
.addItem("フォーム送信", "htmls_mail")
.addItem("フォーム生成と送り付け", "test_sendForm")
.addToUi();
}
//フォーム送信を受け付ける
function doPost(e){
//パラメータを取得する
var ret = makeContent(makeResponse(e,"POST"));
//書き込み用配列を用意する
var array = [];
var params = e.parameter;
//パラメータを配列に格納
array.push(params.email);
array.push(params.blood);
array.push(params.name);
array.push(params.sex);
array.push(params.kanso);
//appendRowで書き込み
var ss = SpreadsheetApp.openById(sheetid);
var sheet = ss.getSheetByName("Sheet1");
sheet.appendRow(array);
//取得結果をそのままリターン
return ret;
}
//投稿内容をJSONで組み立てて返す
function makeResponse (e, type) {
e.parameter.valid = "20202020"; //適当な数値いれてテスト
var s = JSON.stringify({type: type, params: e});
if (!e.parameter.callback) {
return {mime:ContentService.MimeType.JSON, content: s};
}
else {
return {mime: ContentService.MimeType.JAVASCRIPT, content: e.parameter.callback + "(" + s + ");" };
}
}
//投稿コンテンツ内容をJSONで返す
function makeContent(content) {
return ContentService.createTextOutput(content.content).setMimeType(content.mime);
}
//現在のユーザのアドレスを取得
function GetUser() {
var objUser = Session.getActiveUser();
return objUser.getEmail();
}
//HTML Serviceを使ったCSSメール送信
function htmls_mail(){
//HTMLサービスでCSSを取得
var css = HtmlService.createHtmlOutputFromFile('css')
.setSandboxMode(HtmlService.SandboxMode.IFRAME).getContent();
var html = HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME).getContent();
//ヘッダー部分
var formbody = "";
var csshead = "<head><style>";
var cssfoot = "</style></head>";
formbody = csshead + css + cssfoot + "<body>" + html + "</body>";
//メールを送信
MailApp.sendEmail({
to: GetUser(),
subject: "CSSメールテスト",
htmlBody: formbody,
name: "HTML ServiceなCSSメール",
noReply: true
});
}
- 利用する場合は、必ず一度ウェブアプリケーションとして公開し、公開URLを取得する必要があります。
- 公開URLは次のHTML内(index.html)で、FORMの送信先URLとして利用するので、最低でも2回は、ウェブアプリケーションとして版を重ねて公開が必要になります。
- ボタンやテキストボックス等は、CSSで装飾ができるので、別途css.html内に装飾用のCSSコードを記述してあります。
- makeResponseやmakeContentはJSON形式に加工するために利用しています。
- doPostで受け取って、スプレッドシートに書き込みをしています。また、この時、returnではJSONの内容を返していますが、別のHTMLファイルを用意して、返して上げれば「ありがとう表示」をできるようになるので、実運用時にはもうひとつHTMLを用意して、HTML Serviceで表示してあげましょう。
HTML側コード
<form action="ここにウェブアプリケーションとして公開した時のURLを記述する" method="post" class="contact-form">
<p>お客様の情報をご記載下さい。</p>
<div class="item">
名前:<input type="text" name="name" size="40">
</div>
<div class="item">
メール:<input id="e-mail" type="email" name="email">
</div>
<div class="item">
性別:<input type="radio" name="sex" value="male">男
<input type="radio" name="sex" value="female">女
</div>
<div class="item">
血液型:<select name="blood">
<option value="A">A型</option>
<option value="B">B型</option>
<option value="O">O型</option>
<option value="AB">AB型</option>
</select>
</div>
<div class="item">
ご感想:<br>
<textarea name="kanso" rows="4" cols="40"></textarea>
</div>
<div class="item">
<input type="submit" value="送信" class="btn-square-little-rich"><input type="reset" value="リセット" class="btn-square-little-rich">
</div>
</form>
今回のサンプルは、リファレンスのコードに1つメールアドレスを足し、CSS装飾するようにしました。それぞれの項目のname属性はユニークな値を記述するようにしてください。また、formタグのactionには、前項で取得したウェブアプリケーションのURLを指定します。
CSS側コード
今回のコードは関連リンク先に公開されているCSSデザインを利用させていただきました。css.htmlに記述しています。
.contact-form {
border: 1px solid #ccc;
padding: 10px;
font-size: 13px;
font-family: sans-serif;
}
.contact-form .item {
display: block;
overflow: hidden;
margin-bottom: 10px;
}
.contact-form .item.no-label {
padding: 5px 0px 5px 60px;
}
.contact-form .item .label {
float: left;
padding: 5px;
margin:0;
}
.contact-form .item .radio-group{
padding: 5px 0px 5px 60px;
}
.contact-form .item input[type=text],
.contact-form .item input[type=email],
.contact-form .item textarea {
display: block;
margin-left: 60px;
width: 200px;
padding: 5px;
border: 1px solid #ccc;
box-sizing: border-box;
font-size: 13px;
}
.contact-form .item ::placeholder {
color: #ccc;
}
.contact-form .item textarea {
outline: none;
border: 1px solid #ccc;
resize: vertical;
background:#f1f442;
}
input[type=submit] {
border: none;
outline: none;
display: block;
line-height: 30px;
width: 160px;
text-align: center;
font-size: 13px;
color: #fff;
background-color: #696;
border-bottom: 4px solid #464;
cursor:pointer;
box-sizing: content-box;
transition:0.1s ease all
}
input[type=submit]:hover{
opacity:0.6;
}
.btn-square-little-rich {
position: relative;
display: inline-block;
padding: 0.25em 0.5em;
text-decoration: none;
color: #FFF;
background: #03A9F4;/*色*/
border: solid 1px #0f9ada;/*線色*/
border-radius: 4px;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.2);
text-shadow: 0 1px 0 rgba(0,0,0,0.2);
}
.btn-square-little-rich:active {
/*押したとき*/
border: solid 1px #03A9F4;
box-shadow: none;
text-shadow: none;
}
doPostで受信したデータ
上記のコードで発信したメール上から、フォーム送信をすると、doPostで受け取ります。そして、doPostはreturnでそれを加工して返すようにしていますが、その際に加工して返してあげています。素の状態でdoPostで受け取ったデータは以下のような感じ。
{
parameter={
kanso=ガソリン, sex=male, name=キャラメルマン, blood=AB, email=turbo@penguin.jp
},
contextPath=,
contentLength=154,
queryString=,
parameters={
kanso=[Ljava.lang.Object;@52fa97aa,
sex=[Ljava.lang.Object;@72523afa,
name=[Ljava.lang.Object;@de431ca,
blood=[Ljava.lang.Object;@af2b550,
email=[Ljava.lang.Object;@cb32463
},
postData=FileUpload
}
parameterの項目だけ引ければ良いのですが、一応加工すると以下のような感じになります。
{
"type":"POST",
"params":
{
"parameter":
{
"kanso":"ガソリン",
"sex":"male",
"name":"キャラメルマン",
"blood":"AB",
"email":"turbo@penguin.jp",
"valid":"20202020"
},
"contextPath":"",
"contentLength":154,
"queryString":"",
"parameters":
{
"kanso":["ガソリン"],
"sex":["male"],
"name":["キャラメルマン"],
"blood":["AB"],
"email":["turbo@penguin.jp"]
},
"postData":
{
"type":"application/x-www-form-urlencoded",
"length":154,
"contents":"name=%E3%82%AD%E3%83%A3%E3%83%A9%E3%83%A1%E3%83%AB%E3%83%9E%E3%83%B3&email=turbo%40penguin.jp&sex=male&blood=AB&kanso=%E3%82%AC%E3%82%BD%E3%83%AA%E3%83%B3",
"name":"postData"
}
}
}
強引にFormを生成してメールで送る
概要
FormAppにはフォームをメールで送るメソッドが存在しません。そこで、Stackoverflowにて紹介されていた手法がありますが、かなり強引な手法で、送れるには送れるのですが、CSSデザインなどが効いていない状態なので、デザイン的には残念なメールが送られてきました。ただ、GASでFormを生成して、続けてメールで送れるという自動化プロセスは非常に興味深いですね。使い捨てのFormを作って送れる点は、とても有意義だと思います。
このコードはフォームを生成⇒公開時URLにUrlfetchAppでスクレイピング⇒メール本文に貼り付けて送信という手段なので、CSSなどを別途準備できたら、もっと良いものになるのかなぁと思います。
ソースコード
//フォームを生成してメールで送る
function test_sendForm() {
//新しくフォームを生成する
var form = FormApp.create('フォームのファイル名');
var formTitle = 'フォームの名前';
//フォームにオプションを設定
form.setTitle(formTitle)
.setDescription('フォームの説明')
.setConfirmationMessage('フォーム送信時のメッセージ')
.setAllowResponseEdits(true)
.setAcceptingResponses(true)
//ログインを必須とする
try {
form.setRequireLogin(true);
} catch (e) {
//ログインしていない場合にはエラーとなる
}
//1つだけ質問項目を生成する
form.addTextItem().setTitle("Q1");
//ユーザアドレスを取得してフォームを送信
var email = GetUser();
sendForm(form,email)
}
//生成したフォームをメール送信するルーチン
function sendForm(form,email) {
//フォームの公開時アドレスを取得する
var url = form.getPublishedUrl();
//ログイン必須を解除しておく
if (form.requiresLogin()) {
var requiresLogin = true;
//設定はfalseにしておく
form.setRequireLogin(false);
}
//公開URLをスクレイピング
var response = UrlFetchApp.fetch(url);
var htmlBody = HtmlService.createHtmlOutput(response).getContent();
//再度ログイン必須を設定する
if (requiresLogin) {
form.setRequireLogin(true);
}
//メールサブジェクトにフォームタイトルを利用する
var subject = form.getTitle();
//メールを送信する
MailApp.sendEmail(
email,
subject,
'このメールはHTMLメールでの表示が必須です。',
{
name: 'フォームメールスクリプトで送信テスト',
htmlBody: htmlBody
}
);
}
受信した結果
送信ボタンは見当たらないのですが、Enterキーで送信することは可能です。ただ、スクレイピング内容を強引に貼り付けてるだけなので、CSSといったものが一切ありません。そのため下記の図のような表示になります。
図:なんだかオカシナ表示になってしまう。残念
強引にGoogle FormのデータをGASで送る事例の動画
関連リンク
- How to Embed a Google Form in Email in Google App Script
- Embed Google Form in Gmail using Apps Script
- Send form by email and track responses in spreadsheet
- google apps scriptでGoogle formsを生成する
- Googleフォームの結果を指定したアドレスに送る
- HTML入力フォームの作成、徹底ガイド(サンプル付)
- CSSで作る!押したくなるボタンデザイン100(Web用)
- html-form-send-email-via-google-script-without-server



ありがとうございます!
まさに、まさに欲しかった情報ですっっごく助かります!!!
iPhone上のGmailアプリから実行すると「doGet関数がありません」と言われるので、doPostをdoGetにコピペし、gsの
> var ret = makeContent(makeResponse(e,”POST”));
のPOSTをGETに、htmlの
> method=”post”
のpostもgetにすると、携帯でもなんか動きました。
これからも参考にさせていただきます。
ありがとうございます!!!
どうしても、Google Formのみだと限界がありますが、ちょっとだけそこを超えて自前でフォーム作れると世界が一気に広がりますね。
自分もiPadのGmailで一度テストしてみようと思います。