
在使用 google apps script 自动化发送 html 邮件时,一个常见需求是从 google 表格中读取包含多行文本的数据,并将其在邮件中以正确的换行格式呈现。通常,我们会将表格中的 \n 换行符转换为 html 的 <br /> 标签,以便在 html 内容中实现换行。然而,当这些包含 <br /> 标签的字符串通过 htmlservice.createtemplatefromfile() 和 evaluate().getcontent() 处理后,我们可能会发现 <br /> 标签并没有被浏览器解析为换行,而是直接显示为
这样的纯文本。
这个问题的根本原因在于 HtmlService.evaluate().getContent() 方法在生成最终 HTML 内容时,为了安全考虑,默认会对所有动态插入的变量内容进行 HTML 实体转义。这意味着,像 < 和 > 这样的特殊字符会被转换为 。虽然这种行为有助于防止跨站脚本攻击 (XSS),但它也阻止了我们期望的 <br /> 标签被正确解析。
考虑以下 Apps Script 代码片段,它尝试从电子表格中获取文本,将 \n 替换为 <br />,然后将其插入到 HTML 模板中:
// 假设此函数从B4单元格获取文本,并将其中的\n转换为<br />
function splitTest() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Settings");
var str = ss.getRange("B4").getValue(); // 例如 "Hello\nI'm here!"
var array1 = str.split("\n"); // ["Hello", "I'm here!"]
var cMessage = array1.join("<br />"); // "Hello<br />I'm here!"
return cMessage; // 返回包含<br />的字符串
}
function sendMail() {
var emailTemp = HtmlService.createTemplateFromFile("email");
var cMessage = splitTest(); // 获取 "Hello<br />I'm here!"
emailTemp.cmess = cMessage; // 将其赋值给模板变量
var htmlMessage = emailTemp.evaluate().getContent(); // 此时 cmess 会被转义
// htmlMessage 内部可能包含 "Hello<br />I'm here!"
// ... 其他邮件发送逻辑
GmailApp.sendEmail(
"recipient@example.com",
"Subject",
"Please open HTML format",
{
htmlBody: htmlMessage,
}
);
}以及对应的 HTML 模板文件 email.html 中的相关部分:
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt; white-space:pre-line;">
<span style="font-size: 11pt; font-family: Arial;">
<?= cmess ?>
</span>
</p>尽管 p 标签上设置了 white-space:pre-line; 样式(它能将 \n 转换为换行),但由于 cmess 变量中的 <br /> 已经被转义为
,浏览器仍然会将其视为普通文本,从而导致换行失效。
立即学习“前端免费学习笔记(深入)”;
解决这个问题的关键在于,在 HtmlService.evaluate().getContent() 生成了转义后的 HTML 字符串之后,但在将其用于 GmailApp.sendEmail 之前,手动将 替换回 < 和 >。这样,原本被转义的 <br /> 标签就能恢复其作为 HTML 标签的功能。
我们可以使用 JavaScript 的 String.prototype.replace() 方法配合正则表达式来完成这个任务。
function sendMailCorrected() {
var emailTemp = HtmlService.createTemplateFromFile("email");
var cMessage = splitTest(); // 获取 "Hello<br />I'm here!"
emailTemp.cmess = cMessage;
var htmlContent = emailTemp.evaluate().getContent(); // 此时内容为 "Hello<br />I'm here!"
// 核心解决方案:反转HTML实体转义
var unescapedHtmlContent = htmlContent.replace(/</g, "<");
unescapedHtmlContent = unescapedHtmlContent.replace(/>/g, ">");
// ... 其他邮件发送逻辑
GmailApp.sendEmail(
"recipient@example.com",
"Subject",
"Please open HTML format",
{
htmlBody: unescapedHtmlContent, // 使用反转后的内容
}
);
}通过这两行 replace() 操作,htmlContent 中的所有 都会被替换回 < 和 >,从而使 <br /> 标签能够被邮件客户端正确解析并实现换行。
以下是结合了上述解决方案的完整 Apps Script 邮件发送流程:
/**
* 从电子表格指定单元格获取文本,并将内部的 '\n' 转换为 '<br />'。
* @returns {string} 包含 HTML 换行符的字符串。
*/
function splitTest() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Settings");
var str = ss.getRange("B4").getValue(); // 从B4单元格获取文本
var array1 = str.split("\n"); // 按换行符分割
var cMessage = array1.join("<br />"); // 用 <br /> 连接
return cMessage;
}
/**
* 发送 HTML 格式的邮件,并正确处理从电子表格获取的换行符。
*/
function sendMail() {
// 定义列索引,方便维护
var emailCol = 5; // 邮件地址所在列 (从0开始)
var checkboxCol = 6; // 筛选复选框所在列 (从0开始)
var wsRecipients = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Recipients");
var wsSettings = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Settings");
// 从Settings工作表获取邮件主题和发件人名称
var subject = wsSettings.getRange("B1").getValue();
var senderName = wsSettings.getRange("B2").getValue();
// 获取处理后的邮件内容字符串
var cMessage = splitTest();
// 创建 HTML 模板
var emailTemp = HtmlService.createTemplateFromFile("email");
emailTemp.cmess = cMessage; // 将处理后的内容赋值给模板变量
// 评估模板并获取原始 HTML 内容(此时 <br /> 已被转义)
var rawHtmlContent = emailTemp.evaluate().getContent();
// 核心步骤:反转 HTML 实体转义
var unescapedHtmlContent = rawHtmlContent.replace(/</g, "<");
unescapedHtmlContent = unescapedHtmlContent.replace(/>/g, ">");
// 获取收件人数据并筛选
var recipientData = wsRecipients.getRange("A2:G" + wsRecipients.getLastRow()).getValues();
recipientData = recipientData.filter(function(row){
return row[checkboxCol] === true; // 筛选出勾选的收件人
});
// 遍历收件人并发送邮件
recipientData.forEach(function(row){
var recipientEmail = row[emailCol];
GmailApp.sendEmail(
recipientEmail,
subject,
"请打开Html格式以阅读邮件,谢谢!", // 纯文本备用内容
{
name: senderName,
htmlBody: unescapedHtmlContent, // 使用反转后的 HTML 内容
}
);
});
Logger.log("邮件发送完成。");
}<html>
<head>
<base target="_top">
</head>
<body>
<div align="left">
<table style="border: none;"><colgroup><col style="width: 487px;" /><col style="width: 115px;" /></colgroup>
<tbody>
<!-- 邮件头部图片等内容 -->
<tr style="height: 99pt;">
<td style="vertical-align: top; background-color: #f4cccc;">
<p style="line-height: 1.2; text-align: justify; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial;"><span style="border: none;"><img src="https://drive.google.com/uc?id=1rRVBhFpEbp8bjGI9jqWlbn_6K8H4djAv" width="438" height="158" /></span></span></p>
</td>
<td style="border-right: 1pt solid #ffffff; border-bottom: 1pt solid #ffffff; border-top: 1pt solid #ffffff; vertical-align: top; background-color: #f4cccc;">
<p style="line-height: 1.2; text-align: right; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial;"><span style="border: none;"><img src="https://drive.google.com/uc?id=1vwNZtLRAnoRX5WuEWeojEKMf6lOOYbre" width="67" height="137" /></span></span></p>
</td>
</tr>
<!-- 邮件主要内容区域 -->
<tr style="height: 470.66pt;">
<td style="border-left: 1pt solid #ffffff; border-right: 1pt solid #ffffff; vertical-align: top;" colspan="2">
<!-- 可以有其他模板变量,如 cbegin, cend -->
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial;"><?= cbegin ?></span></p>
<br />
<!-- 插入动态内容 cmess -->
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt; white-space:pre-line;"><span style="font-size: 11pt; font-family: Arial;">
<?= cmess ?>
</span></p>
<br /><br /><br />
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial;"><?= cend ?></span></p>
</td>
</tr>
<!-- 邮件底部信息 -->
<tr style="height: 60.1465pt;">
<td style="vertical-align: top; background-color: #f4cccc;">
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><strong><span style="font-size: 9pt; font-family: Arial;">Formosa Chinesische Sprachschule e.V.</span></strong></p>
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 9pt; font-family: Arial;">Schulort : Geschwister-Scholl-Gymnasium Düsseldorf</span></p>
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 9pt; font-family: Arial;">Redinghovenstraße 41, 40225 Düsseldorf</span></p>
<p style="line-height: 1.2; margin-top: 0pt; margin-bottom: 0pt;"><strong><span style="font-size: 9pt; font-family: Arial;">Email: </span></strong><a style="text-decoration: none;" href="mailto:info@formosa.de"><strong><span style="font-size: 9pt; font-family: Arial; color: #1155cc; text-decoration: underline; text-decoration-skip-ink: none;">info@formosa.de</span></strong></a></p>
</td>
<td style="border-right: 1pt solid #ffffff; border-bottom: 1pt solid #ffffff; border-top: 1pt solid #ffffff; vertical-align: top; background-color: #f4cccc;"> </td>
</tr>
</tbody>
</table>
</div>
</body>
</html>安全性考量: 手动反转 HTML 实体转义会降低应用程序的安全性。如果 cMessage 变量中包含的是用户直接输入的、未经净化的数据,那么攻击者可能会注入恶意 HTML 或 JavaScript 代码(如 <script>alert('XSS');</script>),从而导致跨站脚本攻击 (XSS)。
white-space: pre-line; 的作用: HTML 模板中的 white-space:pre-line; 样式在处理 \n 字符时非常有用,它会保留文本中的换行符和空格,并在必要时折行。然而,它无法处理已经被转义的 HTML 标签。因此,当 <br /> 标签被转义为
时,white-space:pre-line; 无法将其识别为换行标签。本教程的解决方案正是为了解决 <br /> 标签被转义的问题。
调试技巧: 在开发过程中,使用 Logger.log() 打印中间变量的值是非常有用的。例如,您可以打印 cMessage、rawHtmlContent 和 unescapedHtmlContent 来观察它们在不同阶段的内容,从而更好地理解数据流和转义过程。
Logger.log("cMessage: " + cMessage);
Logger.log("rawHtmlContent: " + rawHtmlContent);
Logger.log("unescapedHtmlContent: " + unescapedHtmlContent);在使用 Google Apps Script 发送 HTML 邮件并从电子表格动态插入内容时,HtmlService.evaluate().getContent() 的默认 HTML 实体转义行为可能会导致像 <br /> 这样的 HTML 标签无法正确解析。通过在发送邮件前,手动将 反转回 < 和 >,我们可以确保这些标签被邮件客户端正确渲染。在实施此解决方案时,务必注意安全性,确保只对可信内容执行此操作。
以上就是Apps Script HTML 邮件中正确处理换行符的教程的详细内容,更多请关注php中文网其它相关文章!
HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号