高级功能
邮件追踪 (track)
邮件追踪能够帮助用户收集已发出邮件的「打开数据」,「点击数据」,「退订数据」, 以此来评估邮件发送的效果.
你可以通过【发送设置】-【追踪选项】
来配置某个「API_USER」的「打开追踪」,「点击追踪」,「订阅追踪」.
配置追踪域名
使用 ICP 备案通过的域名或其子域名作为追踪域名
配置此域名的 CNAME 记录到 track.sendcloud.org
技术原理
假设客户使用的追踪域名是 track.ifaxin.com,客户需要配置
track.ifaxin.com CNAME track.sendcloud.org
打开追踪
SendCloud 会在客户邮件的末端放置1张1像素的透明图片,一般情况 MP 的客户端、网页端会自动下载邮件中的图片
当用户打开这封邮件时,用户的邮件客户端会请求下载这张1像素的图片,此时 SendCloud 的 track 服务会记录这次打开操作
点击追踪
- 假设客户邮件中有一个链接:http://www.ifaxin.com
- SendCloud 会修改此链接的 href 值变成:http://track.ifaxin.com?p=xxx
- 用户点击链接时,链接会通过 CNAME 记录先请求到 track.sendcloud.org 的 track 服务
- 在完成相应的点击记录之后,track 服务会将此请求 301 到客户的原始链接:http://www.ifaxin.com
取消订阅追踪
SendCloud 会在客户邮件的末端放置1个取消订阅的链接,用户点击此链接会进入取消订阅样式的页面,SendCloud 会记录此用户的邮箱加入到相应的取消订阅列表
取消订阅的链接如图:
地址列表
地址列表是一个方便客户发送邮件的功能. 客户编辑/导入地址列表后, 在请求接口时, 不需要再传输邮件地址, 只需在参数中指定地址列表的「别称地址」即可.
地址列表中可以设置「变量的值」, 用于替换「邮件内容」中的「变量」.
客户可以通过【发送相关】-【地址列表】
来创建【地址列表】.
注意:
- 只有通过 WEBAPI 的方式发送邮件, 才支持使用地址列表. SMTP 接入方式暂不支持.
- 只有使用 「批量类型」的 API_USER 调用接口, 才支持使用地址列表
- 只有付费用户才支持使用地址列表
标签 (label)
标签能够帮助客户对邮件进行分类, 适用于 A/B 测试等场景.
给2种风格的邮件赋予不同的标签进行测试发送, 通过标签分别查看2种风格邮件的打开/点击数据 就能知道接收者最喜欢哪种邮件了~
注意: 每封邮件只能使用一个标签
收信路由
如果你能收到你的用户的回信, 那真是一件让人激动的事情, 所以, SendCloud 为你准备了这个贴心的功能.
此功能就是把用户回复
到某地址的邮件转发给你设置的邮箱, 或是你设置的某个URL. 你可以接收邮件数据, 再做后续处理.
直接发给这个地址的邮件默认不会被转发.
客户可以通过某个域名配置里面的【收信配置】-【添加收信路由】
来创建收信路由.
订阅关系
订阅关系的作用是帮助客户创建, 维护和用户的订阅关系, 帮助客户快速搭建自己的邮件订阅系统.
SendCloud 和 ESP 都在推进建立用户和用户订阅关系, 也会大力支持这种存在订阅关系的邮件发送 ( 比如 QQ邮件列表 ).
-
客户在 SendCloud 中配置生成一个「订阅关系」:
-
客户将生成的 JS 代码放置在自己的网站中
-
用户访问客户的网站时, 输入邮箱地址, 订阅某条信息
-
用户的邮箱地址自动加入客户的某个「地址列表」.
-
用户收到确认邮件, 确认订阅操作.
-
这样, 用户就完成了和客户网站的订阅关系.
此功能依赖于「地址列表」, 客户在配置订阅关系时需要将此订阅关系绑定到某个「地址列表」.
取消订阅样式
在开启「订阅追踪」后, 系统会在邮件中默认自动加上 取消订阅 的退订链接, 供收件人退订此类邮件.
下面是系统默认的取消订阅样式:
你可以自行定义取消订阅的样式, 只要在 href 中插入 SendCloud 内部变量 %%user_defined_unsubscribe_link%%
即可. 示例如下:
使用默认的取消订阅样式, 邮件无需特别处理, 内容如下:
<p>亲爱的%name%:</p>
<p style="margin-bottom: 35px">您好! 您本月在爱发信的消费金额为: %money% 元.</p>
邮件内容效果截图如下:
使用自定义的取消订阅样式, 邮件内容如下:
<p>亲爱的%name%:</p>
<p style="margin-bottom: 35px">您好! 您本月在爱发信的消费金额为: %money% 元.</p>
<p><a style="background: #1ABC9C;border:1px solid #13A386;padding:8px 20px;color: #fff;text-decoration:none;border-radius:4px" href="%%user_defined_unsubscribe_link%%">不想再收到此类邮件</a></p>
邮件内容效果截图如下:
WebHook
客户将邮件请求发送给 SendCloud 之后, SendCloud 会把「请求结果」同步返回给客户, 而邮件的「发送结果」和「其他事件结果」是通过 WebHook 异步返回给用户的.
WebHook 机制:
- SendCloud 为客户提供了一些邮件事件, 客户可以选择关注某些事件
- 当某事件发生, 就会触发 SendCloud 向客户设置的 URL 发送数据 ( POST )
- SendCloud推送的数据类型:"Content-Type: application/x-www-form-urlencoded"
- 客户收到数据, 解析出事件和数据, 你需要在 3s 内返回HTTP Status Code 200, 否则, SendCloud 将会重发该条消息.点此查看WEBHOOK解析示例
目前 SendCloud 支持的邮件事件如下:
事件 | 触发条件 |
---|---|
请求(request) | 邮件请求成功 |
发送(deliver) | 邮件发送成功 |
打开(open) | 用户打开邮件 |
点击(click) | 用户点击链接 |
取消订阅(unsubscribe) | 用户取消订阅邮件 |
举报(report_spam) | 用户举报邮件 |
无效邮件(invalid) | 邮件未发送成功 |
软退信(soft_bounce) | 接收方拒收该邮件 |
转信(route) | 转信/收信路由 |
使用方法:
- 客户自行编写 HTTP 服务, 使之能够处理相应的事件, 解析相关数据, 并开放出相应 URL
- 客户在 SendCloud 的
【邮件】- 【发送设置】-【WebHook】
中选择关注的事件, 配置接收数据的 URL
注意: 我们会对用户提供的 URL 做检测. 需要此 HTTP 服务能够正确响应 get | post 请求, 并且保证返回的 HTTP 状态码 为 200。
签名验证
为了确保消息的来源身份是 SendCloud, 你可以选择对 POST 数据的来源进行安全认证. ( 不验证, 直接解析 POST 的数据也可以 ).
安全认证的方法如下:
- 通过
【发送设置】-【WebHook】
获取APP KEY
- 解析出 POST 数据中的
token
,timestamp
和signature
- 使用
APP KEY
,token
和timestamp
生成签名signature
, 与 POST 数据中的signature
进行校验 ( 签名算法: SHA256)
python 代码示例
import hashlib, hmac
def verify(appkey, token, timestamp, signature):
return signature == hmac.new(
key=appkey,
msg='{}{}'.format(timestamp, token),
digestmod=hashlib.sha256).hexdigest()
Java 代码示例 (依赖 apache codec)
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
public boolean verify(String appkey, String token, long timestamp,
String signature) throws NoSuchAlgorithmException, InvalidKeyException {
Mac sha256HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(appkey.getBytes(),"HmacSHA256");
sha256HMAC.init(secretKey);
StringBuffer buf = new StringBuffer();
buf.append(timestamp).append(token);
String signatureCal = new String(Hex.encodeHex(sha256HMAC.doFinal(buf
.toString().getBytes())));
return signatureCal.equals(signature);
}
php 代码示例
function verify($appkey,$token,$timestamp,$signature){
$hash="sha256";
$result=hash_hmac($hash,$timestamp.$token,$appkey);
return strcmp($result,$signature)==0?1:0;
}
重试机制
如果遇到 URL 访问错误或超时, SendCloud 最多会重试 7 次. 每次重试的时间间隔最快为 3min, 10min, 30min, 1h, 6h, 12h, 24h. 即在消息丢失前, 你有足够的时间来修复 URL.
如果超过重试次数,SendCloud 将会把消息丢弃.
每次事件处理, 数据解析, 你需要在 3s 内返回HTTP Code 200, 否则, SendCloud 将会重发该条消息。
事件说明
目前 WebHook 支持的事件类型包括: 请求, 发送, 打开, 点击, 取消订阅, 举报, 无效邮件.
请求事件 ( request )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"request" |
message | string | 消息内容: "successfully request" |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
messageId | string | messageId |
apiUser | string | API_USER |
category | string | 同 apiUser |
recipientArray | list | 请求的收件人 |
emailIds | list | emailId 数组 |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
recipientSize | int | 本次请求的个数 |
timestamp | long | 时间戳. 事件产生时间 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
发送 ( deliver )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"deliver" |
message | string | 消息内容:"Successfully delivered" |
apiUser | string | API_USER |
category | string | 同 apiUser |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
打开 ( open )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"open" |
message | string | 消息内容:"open email" |
apiUser | string | API_USER |
category | string | 同 apiUser |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
ip | string | 打开的Ip地址 |
explorerName | string | 浏览器名称 |
explorerVer | string | 浏览器版本 |
oSName | string | 操作系统名称 |
oSVer | string | 操作系统版本 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
点击 ( click )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"click" |
message | string | 消息内容:"click email" |
apiUser | string | API_USER |
category | string | 同 apiUser |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
url | string | 被点击的链接 |
ip | string | 点击的Ip地址 |
explorerName | string | 浏览器名称 |
explorerVer | string | 浏览器版本 |
oSName | string | 操作系统名称 |
oSVer | string | 操作系统版本 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
取消订阅 ( unsubscribe )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"unsubscribe" |
message | string | 消息内容:"unsubscribe email" |
apiUser | string | API_USER |
category | string | 同 apiUser |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
ip | string | Ip地址 |
explorerName | string | 浏览器名称 |
explorerVer | string | 浏览器版本 |
oSName | string | 操作系统名称 |
oSVer | string | 操作系统版本 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
垃圾举报 ( report_spam )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"report_spam" |
message | string | 消息内容 |
apiUser | string | API_USER |
category | string | 同 apiUser |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
无效邮件 ( invalid )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"invalid" |
message | string | 消息内容 |
apiUser | string | API_USER |
category | string | 同 apiUser |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
subStatDesc | string | 无效子类描述,eg:IP、域名被拒(5.7.1 Unfortunately, messages...protection.outlook.com]) |
subStat | Integer | 无效子类,eg: 405 |
cause | string | 原始拒信明细信息,eg: 5.7.1 Unfortunately, messages...protection.outlook.com] |
无效子类返回码和描述:
subStat | subStatDesc |
---|---|
401 | 在SendCloud黑名单中 |
402 | 取消订阅 |
403 | 服务器不可达 |
404 | 地址格式错误 |
405 | IP、域名被拒 |
406 | 地址不存在 |
407 | 垃圾邮件 |
408 | 发件人/收件人被拒 |
409 | 其他 |
软退信 ( soft_bounce )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"soft_bounce" |
apiUser | string | API_USER |
category | string | 同 apiUser |
labelId | int | 自定义的标签ID |
labelName | string | 自定义的标签名称 |
maillistTaskId | long | 如果使用地址列表发送,将产生任务id |
mail_list_task_id | long | 同 maillistTaskId |
emailId | string | 每封email的唯一ID |
recipient | string | 收信人 |
timestamp | long | 时间戳 |
token | string | 随机产生的长度为50的字符串 |
signature | string | 签名字符串 |
userHeaders | string | 客户调用发送接口自定义的, 并且以"SC-Custom-"开头的头部信息 |
subStatDesc | string | 软退信子类描述,eg:其他(DIAGNOSTIC-CODE...83.) |
subStat | Integer | 软退信子类,eg: 509 |
cause | string | 原始软退信明细信息,eg: DIAGNOSTIC-CODE: smtp; Your email to group .....https://support.google.com/a/answer/168383. |
软退信子类返回码和描述:
subStat | subStatDesc |
---|---|
503 | 服务不可达 |
505 | ip或域名被拒 |
506 | 邮箱地址不存在 |
507 | 垃圾邮件 |
508 | 发件人/收件人被拒 |
509 | 其他 |
转信 ( route )
参数说明
参数 | 类型 | 说明 |
---|---|---|
event | string | 事件类型:"route" |
from | string | 邮件标头发件人,声称发件人地址,显示在正文的发件人 |
x_mx_mailfrom | string | 信封发件人,实际发件人 |
fromname | string | 发件人名称 |
headers | string | 邮件头部信息. JSON 格式 |
html | string | 转信邮件 html 格式的内容 |
message | string | 消息内容 "mx route" |
raw_message_url | string | 转信文件下载. eg:https:xxx.eml ,链接有效期为15天.JAVA解析eml文件示例 |
signature | string | 签名字符串 |
subject | string | 标题 |
text | string | 转信邮件文本格式的内容 |
timestamp | long | 时间戳 |
to | string | 邮件标头收件人 |
x_mx_rcptto | string | 实际收件人地址 |
token | string | 随机产生的长度为50的字符串 |
toname | string | 收件人名称 |
reference | string | 如果有值,格式为:SendCloud发出邮件的Message-ID(emailid $符号之前的部分)和 '@发信域名' 组成 |
emailId | string | 父邮件的唯一id. 通过此字段,回复邮件可与父邮件进行关联。此值是否有值,取决于收信端的回复邮件是否带有reference头字段 |
eg:"reference":"1644468027883_1024_25239_6195.sg-10_1_253_1-inbound0@ifaxin.com" #ifaxin.com为发信域名
POST 数据示例
maillistTaskId=-1&signature=eb6484eb14a429f7ea367647ffc9bc617ac8ce858afa2705d247f21177760ded&mail_list_task_id=-1&emailId=1576829271482_66557_24087_8851.sc-10_9_13_218-inbound0%24allsa%40sendcloud.cn&message=Successfully+delivered&apiUser=51eat_trigger&token=34szcNvC15W8wxLr1dONdBEuCfn4n4DpxHooDAkGMJf5pG2zVP&userHeaders=%7B%7D&labelId=0&recipient=allsa%40sendcloud.cn&event=deliver&category=51eat_trigger×tamp=1576829272783