Google Apps Script邮件模板replace方法仅部分生效问题
问题描述
使用Google Apps Script实现邮件发送功能,以Google Doc作为邮件模板,通过replace()方法替换模板中的占位符。目前仅{question1}至{question6}能成功替换,{question7}到{question24}无法替换。日志显示文档和邮件内容完整,仅后续占位符未被替换,且已确认占位符文本与模板一致。
代码实现
index.html
<!DOCTYPE html> <html> <head> <base target="_top"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <?!= include('script'); ?> </head> <body> <button id="sendEmailBtn">Send Email</button> </body> </html>
Code.js
function doGet() { return HtmlService.createTemplateFromFile('index').evaluate(); } function include(filename) { return HtmlService.createHtmlOutputFromFile(filename).getContent(); } function sendEmail(data) { let body = createEmailBody(data); MailApp.sendEmail({ to: "*****Your Email*****", subject: "Test Email", htmlBody: body, }); Logger.log("Email length: " + body.length); } function createEmailBody(data) { const templateId = DocumentApp.openByUrl('https://docs.google.com/document/d/1cq8SGVLwfNFAqxDd-LkRDlHCSqyYKuuqYnxO6nfV39k/edit').getId(); let body = docToHtml(templateId); //Convert the template to html Logger.log("Document length: " + body.length) body = body.replace(/{Total Score}/g, data['Total Score']); body = body.replace(/{Overall Totals}/g, data['Overall Totals']); body = body.replace(/{Overall Description}/g, data['Overall Description']); body = body.replace(/{Name}/g, data['Name']); body = body.replace(/{Organization}/g, data['Organization']); body = body.replace(/{question1}/g, data['Question 1']); body = body.replace(/{question2}/g, data['Question 2']); body = body.replace(/{question3}/g, data['Question 3']); body = body.replace(/{question4}/g, data['Question 4']); body = body.replace(/{question5}/g, data['Question 5']); body = body.replace(/{question6}/g, data['Question 6']); body = body.replace(/{question7}/g, data['Question 7']); body = body.replace(/{question8}/g, data['Question 8']); body = body.replace(/{question9}/g, data['Question 9']); body = body.replace(/{question10}/g, data['Question 10']); body = body.replace(/{question11}/g, data['Question 11']); body = body.replace(/{question12}/g, data['Question 12']); body = body.replace(/{question13}/g, data['Question 13']); body = body.replace(/{question14}/g, data['Question 14']); body = body.replace(/{question15}/g, data['Question 15']); body = body.replace(/{question16}/g, data['Question 16']); body = body.replace(/{question17}/g, data['Question 17']); body = body.replace(/{question18}/g, data['Question 18']); body = body.replace(/{question19}/g, data['Question 19']); body = body.replace(/{question20}/g, data['Question 20']); body = body.replace(/{question21}/g, data['Question 21']); body = body.replace(/{question22}/g, data['Question 22']); body = body.replace(/{question23}/g, data['Question 23']); body = body.replace(/{question24}/g, data['Question 24']); return body; } function docToHtml(docId) { // Downloads a Google Doc as an HTML string. let url = 'https://docs.google.com/feeds/download/documents/export/Export?id=' + docId + '&exportFormat=html'; var param = { method: 'get', headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()}, muteHttpExceptions: true, }; let doc = UrlFetchApp.fetch(url, param).getContentText(); Logger.log("Doc length: " + doc.length); return doc; }
script.js
<script> $(document).ready(function() { let btn = document.getElementById('sendEmailBtn'); btn.addEventListener('click', function(){ console.log("clicked"); let emailParams = { 'Total Score': '-Test total score-', 'Overall Totals': '-Test overall totals-', 'Overall Description': '-Test overall description-', 'Name': '-Test name-', 'Organization': '-Test organization-' }; for(let i = 1; i <= 24; i++) { emailParams['Question '+i] = '-Test question' + i + '-'; } google.script.run.sendEmail(emailParams); }); }) </script>
问题分析与解决方案
核心原因
Google Doc导出HTML时,长文档中的占位符可能被自动插入的HTML标签(如<span>、<p>)或换行符拆分,导致replace()无法匹配完整的占位符字符串(比如{question7}可能被拆分为{question<span>7})。
解决方案
1. 正则匹配兼容拆分的占位符
修改createEmailBody中的替换逻辑,用正则表达式忽略中间的HTML标签和空白字符,批量匹配所有问题占位符:
// 替换固定占位符 body = body.replace(/{Total Score}/g, data['Total Score']); body = body.replace(/{Overall Totals}/g, data['Overall Totals']); body = body.replace(/{Overall Description}/g, data['Overall Description']); body = body.replace(/{Name}/g, data['Name']); body = body.replace(/{Organization}/g, data['Organization']); // 批量匹配所有{questionN},允许中间插入HTML标签或空白 body = body.replace(/\{question(\d+)\}/gi, (match, num) => { return data[`Question ${num}`] || match; });
2. 排查导出的HTML原始内容
在docToHtml函数中打印完整HTML内容,确认后续占位符的实际形态:
function docToHtml(docId) { let url = 'https://docs.google.com/feeds/download/documents/export/Export?id=' + docId + '&exportFormat=html'; const param = { method: 'get', headers: {'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()}, muteHttpExceptions: true, }; let doc = UrlFetchApp.fetch(url, param).getContentText(); Logger.log('完整HTML内容:' + doc); // 搜索question7的实际格式 return doc; }
根据日志中占位符的实际格式,调整replace()的匹配规则。
3. 改用纯文本处理模板
如果不需要保留HTML格式,可以直接读取Doc的纯文本内容,避免标签拆分问题:
function createEmailBody(data) { const doc = DocumentApp.openByUrl('你的文档链接'); let body = doc.getBody().getText(); // 获取纯文本 // 执行后续替换逻辑... }
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

