
使用 SendGrid v3 REST API 发送含 HTML 内容的邮件时,若 content.value 中的 HTML 字符串内嵌双引号(如 )未正确转义,会导致 JSON 解析失败,返回 400 Bad Request 错误。解决方案是统一将 HTML 属性值中的双引号改为转义形式 \",确保整个 payload 为合法 JSON。
使用 sendgrid v3 rest api 发送含 html 内容的邮件时,若 `content.value` 中的 html 字符串内嵌双引号(如 ``)未正确转义,会导致 json 解析失败,返回 400 bad request 错误。解决方案是统一将 html 属性值中的双引号改为转义形式 `\"`,确保整个 payload 为合法 json。
在 Go 中调用 SendGrid v3 API(不使用 Mail Helper 类)时,需手动构造符合 SendGrid v3 邮件发送规范 的 JSON 请求体。关键字段 content 是一个数组,其中每个对象包含 type(如 "text/html")和 value(HTML 字符串)。问题根源在于:Go 字符串字面量中直接写入未转义的双引号("),会使外层 JSON 结构非法。
例如,以下写法会破坏 JSON 格式:
content := []map[string]string{
{
"type": "text/html",
"value": "<html><body><a href="http://example.com/reschedule?id=12334">Click</a></body></html>",
},
}此处 href="https://www.php.cn/link/263b1243ca2dbeb358777ceabc4a2e4c 中的 " 会提前结束 Go 字符串,导致编译失败或运行时生成畸形 JSON(如 href="http://https://www.php.cn/link/263b1243ca2dbeb358777ceabc4a2e4c 被截断),最终 SendGrid 服务端解析失败并返回 400 Bad Request。
✅ 正确做法是:对 HTML 字符串中所有属性值的双引号进行 Go 字符串转义(即写成 \"),或更推荐——使用反引号(`)定义原始字符串,并在 HTML 内部保留双引号(但需注意:若 JSON 是通过 json.Marshal 生成,则无需手动转义双引号,而应确保 Go 结构体字段值本身合法)。
立即学习“前端免费学习笔记(深入)”;
推荐实践(安全、清晰、可维护):
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
func sendHTMLEmail() error {
// 构建邮件数据结构(使用 struct 更安全,避免手拼 JSON)
type Content struct {
Type string `json:"type"`
Value string `json:"value"`
}
type Personalization struct {
To []map[string]string `json:"to"`
}
type RequestBody struct {
Personalizations []Personalization `json:"personalizations"`
From map[string]string `json:"from"`
Subject string `json:"subject"`
Content []Content `json:"content"`
}
body := RequestBody{
Personalizations: []Personalization{{
To: []map[string]string{{"email": "recipient@example.com"}},
}},
From: map[string]string{"email": "sender@example.com"},
Subject: "Reschedule Link",
Content: []Content{{
Type: "text/html",
// ✅ 双引号在 Go 字符串中必须转义,或使用变量注入
Value: `<html><body>Hello! You link <a href="http://example.com/reschedule?id=12334">Click</a></body></html>`,
}},
}
jsonBytes, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("marshal request: %w", err)
}
req, _ := http.NewRequest("POST", "https://api.sendgrid.com/v3/mail/send", bytes.NewBuffer(jsonBytes))
req.Header.Set("Authorization", "Bearer YOUR_SENDGRID_API_KEY")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("send request: %w", err)
}
defer resp.Body.Close()
fmt.Printf("Status: %s\n", resp.Status)
return nil
}? 关键注意事项:
- 若手动拼接 JSON 字符串(不推荐),务必对
value中的"全部替换为\",例如:"<a href="%5C%22https://https://www.php.cn/link/263b1243ca2dbeb358777ceabc4a2e4c%5C%22">"</a>; - 使用
json.Marshal()+ Go struct 是最佳实践,它会自动处理 JSON 转义,开发者只需关注 HTML 逻辑本身; - HTML 中的 URL 参数(如
?id=12334)无需额外编码,但若含用户输入内容,务必先做 HTML 实体转义(如html.EscapeString())以防 XSS; - SendGrid 要求
from和to邮箱必须经过验证(除非使用沙盒模式); - 建议始终检查响应状态码与错误体,便于快速定位配置类问题(如密钥失效、发信额度不足等)。
通过结构化构建请求体并依赖标准库序列化,可彻底规避因引号转义不当引发的 400 错误,提升代码健壮性与可维护性。



















