Skip to content

MailHub 事件

MailHub 模块在邮件发送和邮件打开时会上报事件,用于邮件投递追踪和数据分析。

1. 事件概览

MailHub 涉及两类事件:

事件名称触发时机说明
email邮件发送成功时记录每一次邮件投递的详细信息
email_operation邮件被打开时通过 Tracking Pixel 追踪邮件是否被用户打开

每次邮件投递会生成唯一的 message_id(格式:m + base36 编码的 snowflake ID,如 me9971u344wc1),贯穿发送和打开的全链路,可用于将 1 次发送事件与 N 次打开事件进行关联。

2. email 事件(邮件发送)

邮件发送成功后上报 email 事件。

2.1 事件 Schema

字段名称类型说明
tostring收件人邮箱
fromstring发件人邮箱
subjectstring邮件主题
bodystring邮件正文内容
message_idstring邮件投递唯一标识,格式为 m + base36 snowflake ID

2.2 触发场景

email 事件在以下场景中触发:

API 触发发送

客户端或 Server 调用 /mail_hub/send 接口主动发送邮件时,发送成功后上报。

后台任务自动发送

后台任务根据 strategy 配置的 condition(trigger)轮询满足条件的用户,按 timer 配置的时间间隔自动发送邮件,发送成功后上报。

支持的 condition(trigger type):

condition描述
web_sub_no_changeWeb 付费用户,未重置密码
web_sub_and_changeWeb 付费用户,已重置密码
web_no_subWeb 未付费用户
user_manual用户手动触发,不设条件,调用 API 即发送
web_paid_no_loginWeb 平台付费但付费后未登录使用的用户

事件驱动发送

Asset 模块在付费事件发生后通过 SQS 发送事件,MailHub 后台任务监听事件并根据 strategy 配置发送对应邮件,发送成功后上报。

支持的事件类型:

event_type描述
asset.subscription_trial进入试用期
asset.subscription_first_cycle进入第一个订阅周期
asset.subscription_renewing_cycle续订成功,进入下一个订阅周期

Asset 事件格式:

json
{
  "id": "xxx",
  "time": 1729752000,
  "type": "asset.subscription_first_cycle",
  "app_id": "xxx",
  "user_id": "xxx",
  "email": "user@example.com",
  "data": {}
}

TIP

对于同一个事件,id 需要保持唯一性,MailHub 发送邮件时根据 id 进行事件去重。

延迟邮件发送

当用户购买时还未绑定邮箱,且 strategy 开启了 enable_pending_email 配置时,邮件会暂存到 Redis。待用户绑定邮箱后,系统自动发送所有待发送邮件并上报事件。

3. email_operation 事件(邮件打开)

通过 Tracking Pixel(1x1 透明 GIF)追踪邮件是否被用户打开。用户打开邮件时,邮件客户端加载追踪图片,触发 email_operation 事件上报。

3.1 事件 Schema

字段名称类型说明
emailstring收件人邮箱
statusstring操作状态,固定为 open
message_idstring邮件投递唯一标识(与 extra 中的 message_id 一致,便于直接查询)
extrastringJSON 格式扩展数据,包含追踪详情

3.2 extra 字段结构

extra 是一个 JSON 字符串,包含以下字段:

字段名称类型说明
emailstring收件人邮箱
user_idstring用户 ID
message_idstring邮件投递唯一标识
user_agentstring邮件客户端的 User-Agent
ipstring请求来源 IP

3.3 事件示例

json
{
  "email": "user@example.com",
  "status": "open",
  "message_id": "me9971u344wc1",
  "extra": "{\"email\":\"user@example.com\",\"user_id\":\"UXXXX\",\"message_id\":\"me9971u344wc1\",\"user_agent\":\"Mozilla/5.0 ...\",\"ip\":\"203.0.113.1\"}"
}

3.4 Tracking Pixel 接口

接口路径GET /bp/res/i.gif

该接口无需鉴权,嵌入邮件 HTML 中作为 <img> 标签的 src

请求参数(Query String):

参数缩写类型是否必填说明
emailestring收件人邮箱(触发上报的必须参数)
message_idmidstring邮件消息 ID
user_idustring用户 ID,缺省时根据 email 自动查找

注意

emid 同时存在时才会上报打开事件。缺少任一参数仅返回图片,不记录事件。

请求示例:

GET /bp/res/i.gif?e=user%40example.com&u=UXXXX&mid=me9971u344wc1

响应:

  • HTTP 状态码:200
  • Content-Type: image/gif
  • 响应体:1x1 透明 GIF(43 bytes)

响应头包含缓存禁止指令,确保每次打开邮件都会触发请求:

Cache-Control: no-store, no-cache, must-revalidate, max-age=0
Pragma: no-cache

4. 邮件模板变量

4.1 系统变量

以下变量由系统自动注入,适用于所有邮件模板:

变量描述
{{.UserName}}用户名
{{.Email}}用户邮箱
{{.SessionToken}}用户 session token
{{.TrackingPixelURL}}邮件打开追踪图片 URL
{{.MessageID}}邮件消息唯一 ID

4.2 自定义变量

通过 send 接口的 custom_variables 参数传入,在模板中使用 {{.CustomVariables.xxx}} 引用。

系统变量也可通过 CustomVariables 方式引用:

  • {{.CustomVariables.TrackingPixelURL}}
  • {{.CustomVariables.MessageID}}

4.3 Asset 事件模板变量

asset.subscription_trial 事件

变量名称类型格式及举例说明
PurchaseDateYearstring2023试用期开始时间的年份
PurchaseDateMonthstring01, 04, 10, 11试用期开始时间的月份,取值 01-12
PurchaseDateMonthEnglishstringMarch, May试用期开始时间的月份,英文表达
PurchaseDateDaystring01, 02, 27, 31试用期开始时间的日期,取值 01-31
Emailstringabc@example.com用户邮箱
TrialCyclePeriodstring1 day, 2 months, 3 years试用期时长
TrialCycleStartYearstring2023试用期开始时间的年份
TrialCycleStartMonthstring01, 04, 10, 11试用期开始时间的月份,取值 01-12
TrialCycleStartMonthEnglishstringMarch, May试用期开始时间的月份,英文表达
TrialCycleStartDaystring01, 02, 27, 31试用期开始时间的日期,取值 01-31
TrialCycleEndYearstring2023试用期结束时间的年份
TrialCycleEndMonthstring01, 04, 10, 11试用期结束时间的月份,取值 01-12
TrialCycleEndMonthEnglishstringMarch, May试用期结束时间的月份,英文表达
TrialCycleEndDaystring01, 02, 27, 31试用期结束时间的日期,取值 01-31
TrialCyclePricestring3.5 USD, 1.0 HKD试用期价格
RegularCyclePeriodstring1 day, 2 months, 3 years正常周期时长
RegularCycleStartYearstring2023第一期正常周期开始时间的年份
RegularCycleStartMonthstring01, 04, 10, 11第一期正常周期开始时间的月份,取值 01-12
RegularCycleStartMonthEnglishstringMarch, May第一期正常周期开始时间的月份,英文表达
RegularCycleStartDaystring01, 02, 27, 31第一期正常周期开始时间的日期,取值 01-31
RegularCyclePricestring3.5 USD, 1.0 HKD正常周期的价格
PlatformstringSTRIPE, PAYPAL支付平台
TransactionIDstringin_1N4bGzJeDjdpBmRtPcInXgOs支付平台交易 ID

asset.subscription_first_cycle / asset.subscription_renewing_cycle 事件

变量名称类型格式及举例说明
PurchaseDateYearstring2023当期付费时间的年份
PurchaseDateMonthstring01, 04, 10, 11当期付费时间的月份,取值 01-12
PurchaseDateMonthEnglishstringMarch, May当期付费时间的月份,英文表达
PurchaseDateDaystring01, 02, 27, 31当期付费时间的日期,取值 01-31
Emailstringabc@example.com用户邮箱
RegularCyclePeriodstring1 day, 2 months, 3 years正常周期时长
RegularCycleStartYearstring2023当前周期开始时间的年份
RegularCycleStartMonthstring01, 04, 10, 11当前周期开始时间的月份,取值 01-12
RegularCycleStartMonthEnglishstringMarch, May当前周期开始时间的月份,英文表达
RegularCycleStartDaystring01, 02, 27, 31当前周期开始时间的日期,取值 01-31
RegularCycleEndYearstring2023当前周期结束时间的年份
RegularCycleEndMonthstring01, 04, 10, 11当前周期结束时间的月份,取值 01-12
RegularCycleEndMonthEnglishstringMarch, May当前周期结束时间的月份,英文表达
RegularCycleEndDaystring01, 02, 27, 31当前周期结束时间的日期,取值 01-31
RegularCyclePricestring3.5 USD, 1.0 HKD当前周期的价格
PlatformstringSTRIPE, PAYPAL支付平台
TransactionIDstringin_1N4bGzJeDjdpBmRtPcInXgOs支付平台交易 ID

TIP

在邮件模板中使用 Go 模板语法引用变量,如 {{.Platform}}{{.RegularCyclePeriod}}

5. Strategy 配置

MailHub 通过 Console 配置 strategy 来管理邮件发送规则。Strategy 分为两种类型:

5.1 API 类型

由客户端或服务端调用 API 触发发送,支持 condition 和 timer 配置。

json
{
  "name": "strategy_name",
  "type": "api",
  "condition": "web_sub_no_change",
  "timer": [
    {
      "interval": "5m",
      "repeat": false,
      "content_name": "change_password_email"
    },
    {
      "interval": "30m",
      "repeat": false,
      "content_name": "change_password_email"
    }
  ],
  "description": "web 付费用户未重置密码提醒",
  "email_from": "noreply@example.com"
}
字段类型必填说明
namestring策略名称,API 调用时使用
typestring固定为 api
conditionstring触发条件(trigger type),见上方 condition 列表
timerarray定时发送配置
timer[].intervalstring发送间隔,如 5m1h24h
timer[].repeatbool是否重复发送
timer[].content_namestring邮件内容模板名称
descriptionstring策略描述
email_fromstring发件人邮箱,不填使用默认配置
enable_api_emailbool是否允许通过 API 指定收件人邮箱,默认 false

5.2 Event 类型

由 Asset 模块的付费事件驱动发送,不支持 timer 配置。

json
{
  "name": "strategy_name",
  "type": "event",
  "event_type": "asset.subscription_first_cycle",
  "event_email_content_name": "receipt_email",
  "description": "首次订阅收据邮件",
  "email_from": "noreply@example.com",
  "enable_pending_email": true,
  "pending_email_delay": "72h"
}
字段类型必填说明
namestring策略名称
typestring固定为 event
event_typestring事件类型,见上方 event_type 列表
event_email_content_namestring邮件内容模板名称
descriptionstring策略描述
email_fromstring发件人邮箱,不填使用默认配置
enable_pending_emailbool是否启用延迟邮件发送,默认 false
pending_email_delaystring延迟发送的过期时间,如 72h2m,超过此时间不再发送

TIP

使用 Event 类型 strategy 前,需要在 Console 的 Asset 模块开启 MailHub 事件开关: Asset -> Basic Config -> Mailhub Config -> Enable Mailhub Event

6. 数据关联与分析

6.1 通过 message_id 关联发送与打开

每次邮件投递生成唯一 message_id,同时存在于:

  • email 事件的 message_id 字段
  • email_operation 事件的 message_id 字段和 extra JSON 中

通过 message_id 可以:

  • 将 1 次发送(email)事件与 N 次打开(email_operation)事件关联
  • 区分邮件服务器预览与用户真实打开
  • 计算邮件打开率

6.2 注意事项

WARNING

  • Tracking Pixel 仅在 HTML 格式的邮件中有效。
  • 部分邮件客户端(如 Outlook 某些版本)默认不加载外部图片,此时无法追踪。
  • 追踪数据为统计参考,不保证 100% 准确。
  • AWS SES 邮件发送服务对发送失败率有监控,如果发送过多失败的邮件(如地址错误),可能会被 AWS 暂停服务。

京ICP备19011570号-2