Google Formはフォームとしてページを表示するだけでなく、メールの中にフォームを埋め込んで送ることが可能です。しかし、FormAppには、フォームを作成するメソッドは合っても、Google Apps Scriptからそれを埋め込んだメールを送るメソッドが存在しません。そのため、メールで送るには、1人ずつ手動で、Google Form上で作業をしなければならない。
そこでGoogle Formを使わずに、フォームメールを作り、データをスプレッドシートに直接格納することはできないだろうか?と考えたのが今回の手法です。尚、Google Formのフォームメールも、今回の手法もスマートフォンのGMailアプリ上では入力が出来ません (セキュリティの関係上)。PC上では問題なく入力が可能です。
図:きちんとValidationも働く
今回使用するスプレッドシート類
GMail上では、JavaScriptは動きませんが、CSSで装飾する事は可能です。また、今回、Submit先は別に用意したdoPostの受け皿のURLを指定しているので、そちらで値を取得することが可能です。
ソースコード
GAS側コード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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側コード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<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に記述しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
.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の項目だけ引ければ良いのですが、一応加工すると以下のような感じになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"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などを別途準備できたら、もっと良いものになるのかなぁと思います。
ソースコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//フォームを生成してメールで送る
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で送る事例の動画
GAS019 How to Embed Google Forms to Gmail
関連リンク
ありがとうございます!
まさに、まさに欲しかった情報ですっっごく助かります!!!
iPhone上のGmailアプリから実行すると「doGet関数がありません」と言われるので、doPostをdoGetにコピペし、gsの
> var ret = makeContent(makeResponse(e,”POST”));
のPOSTをGETに、htmlの
> method=”post”
のpostもgetにすると、携帯でもなんか動きました。
これからも参考にさせていただきます。
ありがとうございます!!!
どうしても、Google Formのみだと限界がありますが、ちょっとだけそこを超えて自前でフォーム作れると世界が一気に広がりますね。
自分もiPadのGmailで一度テストしてみようと思います。