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側コード
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で受け取ったデータは以下のような感じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ 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で送る事例の動画
関連リンク
- 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で一度テストしてみようと思います。