Google 表單,提交後系統自動寄送回覆通知 email

本篇大綱
Toggle2020.08.28更新:因為有人問說「有辦法針對問卷的回應答案不同,給予不同的回覆 email 嗎?」今天新增一個大段落用不同的寄件者信箱寄信 。
2020.08.27更新:因為留言區中有人提問「可否有方法當資料欄位是空白(非必填的),在回覆時也不出現?」今天補充了當有題目是非必填,而使用者也真的沒有填時,要怎麼寫才能不出現在自動回覆的信件中。
本篇要解決的問題
一個線上報名表,如果能在填完單後就收到回覆通知信,可以讓報名者知道自己的報名結果,這樣子的使用體驗是比較好的,至少客服不會接打來詢問報名成功沒的電話接到手軟。
現在很多線上表單都是用Google表單直接製作,但Google表單在介面上,只能選擇當有新提交時,發 email給建立表單的人,而無法直接回信給報名者。
如果要發送信件給報名者,那就是要每隔一段時間用人工手動發送。
本篇要解決的問題就是:怎麼用 Google 表單既有的功能,在收到新提交時,可以用程式自動寄送回覆通知信給報名者。
這邊也建了一個 Demo,可以在這個 Google 表單上填表,送出成功後會收到系統通知信:
https://forms.gle/FLSqPayARHUc7FDq6
Google表單自動發送回覆信件流程圖
整體步驟如下:
- 建立 Google 表單,「回覆」選擇建立試算表。在試算表上,點擊「指令碼編輯器」
- 指令碼編輯器上,除了預設的「程式碼.gs」,再新增一個 HTML 檔案
- 新增的 HTML 貼上我們電子報的程式碼,需要替換的文字寫成變數形式:
<?= 變數 =>
- 編輯「程式碼.gs」:抓取上一步新增的 HTML 檔案、設定變數、是否要用inline images、是否要夾帶附件、發送電子報
- 指令碼編輯器上點擊「現有專案的啟動程序」,在介面中新增觸發條件
1 建立Google表單,回覆的試算表點擊指令碼編輯器
Google表單建立時,一定要有一題是請使用者填寫 email,不然會不知道該寄給誰。
回覆用的試算表建立後,點擊上排的「工具」 > 「指令碼編輯器」:

接著會進到寫程式碼的介面,其實就是到了一個 Google Apps Script 的檔案上,可以在這寫程式碼,看到介面後第一步就完成了。
要注意的是,這份 Google 表單擁有者的帳號,就會是寄件者的帳號。
比方王小明看完了這篇,就用自己的 Google 帳號:[email protected] 來新增了一份表單,那當他照著本篇作完(或是複製貼上完 XD~),當有路人真的來填表了,收到的系統回覆信,寄件者就會寫[email protected]。
因此王小明也可以從 Gmail 的寄件備份中去查看到底寄了多少信出去。
如果想要用不同的信箱寄信,可看本筆記文的最後一段:用不同的寄件者信箱寄信
2 指令碼編輯器,新增HTML檔案
新增的 HTML 檔案就是我們電子報的檔案,要讓 Google Apps Script 抓到 HTML 的檔案,就得新增在這。
滑鼠移到左上角的「檔案」 > 「新增」,點選「HTML 檔案」:

接著取一個檔案名稱後按下確定,就新增完成。
新增完 HTML 檔案,會看到介面上一共有二個檔:程式碼.gs、xxx.html

程式碼.gs 就是寫收到提交後要自動回信的 JavaScript 部份。
XXX.html 就是寫我們回信用的電子報部份。
下一步我們先來處理電子報的內容。
3 電子報的 .html,要替換的文字寫成變數
一般用系統自動回信,為了讓使用者感到親切,大部份都會加上對方的名字,比方:「王小明 您好,很高興您這次參與本次調查」……之類的。
一般發報系統都可以加上一個變數,讓系統去自動替換,像是上面的例子就可能會寫成:「%name%
您好,很高興您這次參與本次調查 」,用的變數符號不一定,就看發報系統的規則。
Google Apps Script 在 HTML 檔案上也有自己的變數規則,就是:<?= 變數 =>
。
第一眼看的時候還以為是 PHP。
另外還有一個變數,但不一定要使用,就是如果想把圖片直接寫進電子報裡,而不是外部引用時,電子報上叫「inline images」,inline images的寫法就是:
<img src="cid:變數名稱">
這個在寫發送的程式碼那段會有補充。
本篇實作的 Demo 為了能反映變數這項功能,所以把 Google 表單上的每一題都設成變數寫進 HTML 裡,完整的 HTML 程式碼如下:
91-94 行就是寫入變數,之後會從程式碼.gs 中抓到使用者提交的資料後做替換。
這邊寫成以下:
填答時間:<?= data.時間戳記 ?>暱稱:<?= data.暱稱 ?>喜好:<?= data.喜好 ?>程度:<?= data.程度 ?>
可以看到變數都帶有data
,這樣我們只需要命 data 這個變數 = 使用者提交的資料,一行就可以替換了。
使用者沒有填寫時,不會出現在信件中
看了一下官方文件,寫在 Google Apps Script 裡的 HTML 檔案,可以加入if
、else
的判斷,上面的原始碼範例中已加入了「喜好」、「程度」這二題不為空值時,才載入<p>
的判斷。
在 HTML 裡寫if
、else
的範例如下:
4 程式碼部份
電子報的 HTML 完成後,下一步就是編輯 程式碼.gs 這個檔案,要做的事情有:
- 抓取上一步新增的HTML檔案
- 設定變數
- 是否要用inline images
- 是否要夾帶附件
- 發送電子報
抓 HTML 檔案
var edmHTML = HtmlService.createTemplateFromFile('HTML的檔案名稱');
比方 August 的 HTML 叫 edm-demo.html,那就寫成以下:
var edmHTML = HtmlService.createTemplateFromFile('edm-demo');
設定變數
我們的 function 會帶一個 datas 的參數進來,像這樣:
function onSubmit(datas) { // ……}
在上一篇Telegram Bot:Google表單提交時收到通知 中有說,當有使用者提交表單時,我們可以收到的訊息主要都在「namedValues」這段,因此我們只要取出 namedValues 就可以知道新的提交有哪些資料。
function onSubmit(datas) { // 取得提交的值 var data = datas.namedValues; var replyEmail = data['email'][0]; // 設定HTML裡的變數 var edmHTML = HtmlService.createTemplateFromFile('edm-demo'); edmHTML.data = data;}
取得 email 欄位,是為了讓程式知道自動回覆信要回覆到哪個 email。
上一段的 HTML 程式碼,把變數都設成了<?= data.暱稱 =>
這種前面加個data
的,因此這邊我們直接把從提交中取得的值命成 HTML 的data
就完成了變數的替換,就是這行:edmHTML.data = data;
inline images
inline images 是把圖片直接用 base64 寫進 HTML 中,不一定要用,用了有一個好處,就是我們一般用 outlook 收信時,圖片都會要按允許下載才會載入,用 inline images 的話就會直接顯示。
// 將 Telegram 圖轉為 inline imagevar telegram = 'https://imgur.com/RvgV92X.png';var telegramBlob = UrlFetchApp.fetch(telegram).getBlob().setName("telegram");// ……inlineImages: { telegram: telegramBlob},
夾帶附件
夾帶附件很方便,可以直接抓 Google 雲端硬碟裡的檔案,只要知道檔案的 id 就行了。
取得檔案 id 的方法,就是對雲端硬碟中要夾帶成附件的檔案點一下,然後點選右上角表示連結的 icon,就會出現一個提示框裡帶有網址:

取得的網址會長這樣:
https://drive.google.com/open?id=xxxxxxxxxxxx
id 後面的 xxxxx 就是這個檔案的 id,有了 id 就可以夾帶成附件,如下:
var file1 = DriveApp.getFileById('xxxxxxxxxxx');var file2 = DriveApp.getFileById('yyyyyyyyyyy');// ……attachments: [file1.getAs(MimeType.PNG), file2.getAs(MimeType.PNG)] // 附件
附件可以多個,包在陣列裡就行。
MimeType 可參考說明文件。
發送電子報
本篇實作的 Demo,包含上述步驟的程式碼如下:
5 設定觸發條件
有了電子報的 HTML,也有了執行自動發送電子報的 function,最後一步就是要設定「當使用者提交時,執行寄送回覆電子報」的觸發條件。
一樣在 Google Apps Script 的介面上,點上面那排的「編輯」 > 「現有專案的啟動程序」:

畫面會進入到設定觸發條件的頁面上,點擊右下角的「新增觸發條件」:

觸發條件的新增,只要確定好二個選項--選擇要執行的功能、活動類型:

選擇要執行的功能,因為我們在上一步寫程式碼時,把處理的動作都寫在onSubmit
這個 function 中,因此這邊就選 onSubmit。
活動類型指的就是什麼時候要觸發,這邊選「提交表單時」,意思就是當有人提交表單,就會執行onSubmit
,onSubmit
裡就是做取資料、取電子報、取附件、發送……等這一系列我們前幾步寫入的動作。
按下儲存後,Google 會跟你要權限的確認,因為是我們自己寫的程式,就一律允許就行。
就這樣,當使用者提交了 Google 表單,系統就會自動寄發回覆信件給填單者。
最後這邊再提供一次本篇實作出的 Demo:
https://forms.gle/FLSqPayARHUc7FDq6
自動回覆的信件中,August 還放上了最近新開的 Telegram 頻道連結,如果想收到 Let’s Write 新文章通知的朋友,歡迎加入~
用不同的寄件者信箱寄信
要用不同的信箱來做自動回覆信件是可以的,但有額外的設定要做,依序為:
- 在 Gmail 新增其他的寄件地址
- Google Apps Script 要關閉 Chrome V8 功能
- 發送 email 換成
GmailApp.sendEmail
新增其他寄件地址
在開 Google Apps Script 的檔案時,檔案擁有者就會是預設的寄件者,而在 Gmail 裡,我們可以用額外的信箱來寄信,稱為「別名 Aliases」,我們的帳號新增完別名,就可以用這些別名來當作寄件者。
進到Gmail 的頁面後,點選右上角的齒輪,再點「查看所有設定」:

進到設定頁,上面的頁籤點「帳戶和匯入」,下面會有一項是「選擇寄件地址」,再點擊「新增另一個電子郵件地址」,新增完後就會出現在列表中:

上圖是已經新增成功的,August 額外新增了 2 個信箱,再加上原本的,列表上會呈現出 3 個。
新增完其他寄件地址後,我們就可以用這些信箱來讓系統自動寄信。
關閉 Chrome V8 功能
進到 Google Apps Script,需要先關掉 Chrome V8 的功能,這樣在抓別名進來時才不會報權限不足的錯誤而卡住。
Google Apps Script 的頁面上點上排的「執行」,接著點「停用……」的那排(字太長懶得打,直接看下面截圖 XD):

停用後,最後就是改我們的程式碼。
GmailApp.sendEmail
文件:getAliases()、sendEmail(recipient, subject, body, options)
在發送信件的函式,原本我們是用MailApp.sendEmail
,但為了能用不同的寄件信箱,我們得改用GmailApp.sendEmail
。
以下的程式碼,會示範:判斷第三題「喜好」的答案,因答案不同,而使用不同的寄件信箱,以及不同的寄件者名稱。
取得所有寄件地址
在第一步中我們建立了 Gmail 上的「其他寄信地址」,這一段程式碼是取得主帳號的信箱 + 其他寄件地址:
我們可以包成一個 function,然後用Logger.log(aliases)
去看aliases
的陣列順序。
寄送信件
寄送信件的 function 如下:
完整的範例程式碼
參考資源
Class MailApp
How to send HTML email in Google Apps Script

