通过 SendGrid API 从命令行发送复杂的 html 作为电子邮件正文
Sending a complex html as the body of email from the command line via an SendGrid API
我需要将 HTML 文件作为电子邮件的正文发送给多个客户。我们公司将为此使用 SendGrid,我需要能够通过 API Curl Call 发送电子邮件。
到目前为止,我的做法适用于简单的 html 或纯文本:
curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"personalizations":[{"to":[{"email":"my1@email.com"},{"email":"my2@email.com"}]}],"from":{"email":"info@somewhere.com"},"subject":"Testing sending emails via SendgridAPI","content":[{"type":"text\/html","value":"Test API Email From ME"}]}'
现在一切正常。问题是当我想用一个相当大、复杂的 HTML 文件的内容替换 'Test API Email From ME' 时。这具有所有常见的 cli 噩梦,例如到处都是 ' 和 " 以及新行。我需要清理 HTML 以完成三件事:
最终结果需要是有效的命令行字符串
--data 开关参数需要保持有效的 JSON 编码字符串
HTML应该不会断。
我所做的是创建实际的字符串命令并使用脚本语言执行它。因此,在将 html 插入内容字段的值字段之前,我可以在 html 上执行任何我想要的操作。所以我的问题是:我应该对 html 执行哪些字符串操作,以便我可以使用这种方法发送电子邮件?
使用 jq
和 bash
我会用静态数据来做,你可以改进它
- 为 API 定义一个 JSON 模板:
IFS='' read -r -d '' json_template <<'EOF'
{
"personalizations": [
{
"to": [
{ "email": "my1@email.com" },
{ "email": "my2@email.com" }
]
}
],
"from": { "email": "info@somewhere.com" },
"subject": "Testing sending emails via SendgridAPI",
"content": [
{
"type": "text/html",
"value": "Test API Email From ME"
}
]
}
EOF
- 定义HTML内容:
IFS='' read -r -d '' html_email <<'EOF'
<!doctype html>
<html>
<head>
title>Simple Email</title>
</head>
<body>
Test API Email From ME
</body
</html>
EOF
- 将JSON中的邮件内容替换为HTML
json_data=$(
jq -c -n \
--arg html "$html_email" \
--argjson template "$json_template" \
'$template | .content[0].value = $html'
)
- 发送查询
curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data "$json_data"
以下是如何使用 jq
编写适当的 JSON 数据负载,以便将其发送到 API。
jq
将确保每个值、收件人、发件人、主题和 html 正文在提交之前分别编码为适当的 JSON 数据对象、数组和字符串--data @-
到 curl
:
我到处都加了注释,所以每一步都做了什么很清楚:
#!/usr/bin/env bash
recipients=(
'my1@email.com'
'my2@email.com'
)
from='info@somewhere.com'
subject='Testing sending emails via SendgridAPI'
# Streams null-delimited recipients array entries
printf '%s[=10=]' "${recipients[@]}" |
# jq slurps the null-delimited recipients,
# read the raw html content into the jq $contentHTML variable
# and integrate it all as a proper JSON
jq --slurp --raw-input --rawfile contentHTML example.html \
--arg from "$from" \
--arg subject "$subject" \
'
# Fills the jq $recipient JSON array variable
# by splitting the null-delmited entries
# from the incoming stream
split( "\u0000") as $recipients |
{
"personalizations": [
{
# Uses the $recipients array that has been
# slurped from the input stream
"to": $recipients
}
],
"from": {
# Use the $from that has been passed as --arg
"email": $from
},
# Use the $subject that has been passed as --arg
"subject": $subject,
"content": [
{
"type": "text/html",
"value": $contentHTML
}
]
}
' |
# Get the resultant JSON piped into curl
# that will read the data from the standard input
# using --data @-
# rather than passing it as an argument, because
# the payload could exceed the maximum length of arguments
curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data @-
我需要将 HTML 文件作为电子邮件的正文发送给多个客户。我们公司将为此使用 SendGrid,我需要能够通过 API Curl Call 发送电子邮件。
到目前为止,我的做法适用于简单的 html 或纯文本:
curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"personalizations":[{"to":[{"email":"my1@email.com"},{"email":"my2@email.com"}]}],"from":{"email":"info@somewhere.com"},"subject":"Testing sending emails via SendgridAPI","content":[{"type":"text\/html","value":"Test API Email From ME"}]}'
现在一切正常。问题是当我想用一个相当大、复杂的 HTML 文件的内容替换 'Test API Email From ME' 时。这具有所有常见的 cli 噩梦,例如到处都是 ' 和 " 以及新行。我需要清理 HTML 以完成三件事:
最终结果需要是有效的命令行字符串
--data 开关参数需要保持有效的 JSON 编码字符串
HTML应该不会断。
我所做的是创建实际的字符串命令并使用脚本语言执行它。因此,在将 html 插入内容字段的值字段之前,我可以在 html 上执行任何我想要的操作。所以我的问题是:我应该对 html 执行哪些字符串操作,以便我可以使用这种方法发送电子邮件?
使用 jq
和 bash
我会用静态数据来做,你可以改进它
- 为 API 定义一个 JSON 模板:
IFS='' read -r -d '' json_template <<'EOF'
{
"personalizations": [
{
"to": [
{ "email": "my1@email.com" },
{ "email": "my2@email.com" }
]
}
],
"from": { "email": "info@somewhere.com" },
"subject": "Testing sending emails via SendgridAPI",
"content": [
{
"type": "text/html",
"value": "Test API Email From ME"
}
]
}
EOF
- 定义HTML内容:
IFS='' read -r -d '' html_email <<'EOF'
<!doctype html>
<html>
<head>
title>Simple Email</title>
</head>
<body>
Test API Email From ME
</body
</html>
EOF
- 将JSON中的邮件内容替换为HTML
json_data=$(
jq -c -n \
--arg html "$html_email" \
--argjson template "$json_template" \
'$template | .content[0].value = $html'
)
- 发送查询
curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data "$json_data"
以下是如何使用 jq
编写适当的 JSON 数据负载,以便将其发送到 API。
jq
将确保每个值、收件人、发件人、主题和 html 正文在提交之前分别编码为适当的 JSON 数据对象、数组和字符串--data @-
到 curl
:
我到处都加了注释,所以每一步都做了什么很清楚:
#!/usr/bin/env bash
recipients=(
'my1@email.com'
'my2@email.com'
)
from='info@somewhere.com'
subject='Testing sending emails via SendgridAPI'
# Streams null-delimited recipients array entries
printf '%s[=10=]' "${recipients[@]}" |
# jq slurps the null-delimited recipients,
# read the raw html content into the jq $contentHTML variable
# and integrate it all as a proper JSON
jq --slurp --raw-input --rawfile contentHTML example.html \
--arg from "$from" \
--arg subject "$subject" \
'
# Fills the jq $recipient JSON array variable
# by splitting the null-delmited entries
# from the incoming stream
split( "\u0000") as $recipients |
{
"personalizations": [
{
# Uses the $recipients array that has been
# slurped from the input stream
"to": $recipients
}
],
"from": {
# Use the $from that has been passed as --arg
"email": $from
},
# Use the $subject that has been passed as --arg
"subject": $subject,
"content": [
{
"type": "text/html",
"value": $contentHTML
}
]
}
' |
# Get the resultant JSON piped into curl
# that will read the data from the standard input
# using --data @-
# rather than passing it as an argument, because
# the payload could exceed the maximum length of arguments
curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data @-