docs: update WishFulfilled knowledge base

This commit is contained in:
qiaoxinjiu
2026-05-29 14:33:56 +08:00
parent e31a75d2bb
commit 3f7f88cf91
29 changed files with 6679 additions and 187 deletions

View File

@@ -0,0 +1,398 @@
# 通用 EDM 业务流程说明
更新时间2026-05-26
## 1. 文档目标
本文用于新的 EDM 子系统设计或重构,目标是在功能保持一致的前提下,将现有 EDM 业务抽象成通用流程,便于后续拆分服务、设计数据模型、规划 Kafka 消费链路、接入邮件发送通道和处理邮件客服工单。
## 2. 业务范围
通用 EDM 子系统建议分为三条业务线:
| 业务线 | 说明 |
| --- | --- |
| 批量营销邮件 | 管理后台创建邮件任务,按标签、站点、产品、用户状态筛选目标用户,生成待发送邮件记录,通过队列异步发送 |
| 自动 / 实时策略邮件 | 根据用户注册、访问、在线、站点、产品、行为、无消息等规则自动筛选用户,并生成策略邮件 |
| 邮件工单 | 用户来信、表单提交或外部收信服务进入后台后,生成或更新邮件工单,由客服处理、回复、转发、关闭 |
如果新系统还需要普通邮箱功能,可以作为独立模块处理。普通邮箱收发不一定进入 EDM 工单链路,是否合并需要单独确认。
## 3. 总体架构
```mermaid
flowchart TD
A["管理后台"] --> B["EDM 任务服务"]
B --> C["目标用户筛选服务"]
C --> D["邮件记录生成服务"]
D --> E["Kafka / 队列"]
E --> F["邮件发送消费者"]
F --> G["外部发送通道"]
G --> H["AWS SES / SMTP / Gmail / Microsoft"]
H --> I["事件回调"]
I --> J["事件处理服务"]
J --> K["统计与黑名单"]
L["用户来信 / 表单提交"] --> M["入站接收服务"]
M --> N["Kafka / 入站队列"]
N --> O["EDM 工单服务"]
O --> P["客服工作台"]
P --> E
```
核心组件职责:
| 组件 | 职责 |
| --- | --- |
| 管理后台 | 创建邮件任务、审核任务、查看统计、处理邮件工单 |
| 任务服务 | 保存任务配置、正文、模板、发送时间、审核状态 |
| 用户筛选服务 | 根据标签、站点、产品、黑名单、订阅状态、发送频率等规则筛选目标用户 |
| 邮件记录服务 | 按用户生成单封待发送邮件记录和正文快照 |
| Kafka / 队列 | 解耦任务生成、邮件发送、入站消息、事件统计 |
| 发送消费者 | 消费待发送邮件,调用外部发送通道,并保存发送结果 |
| 入站接收服务 | 接收表单、用户来信或外部邮件服务回调,写入入站队列 |
| 工单服务 | 根据来信生成或更新邮件工单,维护状态、负责人、未读数和处理记录 |
| 事件处理服务 | 处理送达、打开、点击、退信、投诉、拒信等邮件事件 |
| Redis / 缓存 | 保存并发锁、游标、限流计数、近期任务统计、临时筛选集合 |
## 4. 核心数据模型
新子系统建议至少抽象以下对象:
| 对象 | 说明 |
| --- | --- |
| 邮件任务 EmailTask | 批量营销或策略邮件任务,保存任务名称、类型、发送时间、审核状态、目标条件 |
| 邮件内容 EmailContent | 任务级正文、标题、模板、发件人、回复地址、附件配置 |
| 目标用户 TaskRecipient | 任务命中的用户关系,便于统计和去重 |
| 单封邮件 EmailMessage | 最终发送或接收的一封邮件记录包含方向、收件人、发件人、状态、message_id、工单 ID |
| 邮件正文 EmailBody | 单封邮件正文快照,避免模板后续变化影响历史邮件 |
| 工单 EmailTicket | 用户来信或客服主动发起的一次处理过程 |
| 分配记录 Assignment | 工单分配、移交、释放、代班等操作记录 |
| 节点日志 NodeLog | 创建、分配、首次回复、关闭、未解决、转化中等关键节点 |
| 发送事件 EmailEvent | 送达、打开、点击、退信、投诉、拒信、渲染失败等事件 |
| 黑名单 / 退订名单 Suppression | 退信、投诉、退订、风险用户等不可发送或需谨慎发送的人群 |
## 5. 批量营销邮件流程
```mermaid
flowchart TD
A["后台创建邮件任务"] --> B["校验任务配置"]
B --> C["写入任务、内容、标签条件"]
C --> D["进入待审核"]
D --> E{"审核结果"}
E -->|通过| F["进入待执行"]
E -->|驳回| G["记录驳回原因并结束"]
F --> H["到达发送时间"]
H --> I["筛选目标用户"]
I --> J["生成单封待发送邮件记录"]
J --> K["投递 Kafka"]
K --> L["发送消费者调用外部邮件通道"]
L --> M["更新发送状态和 message_id"]
```
创建任务时建议校验:
1. 任务名称不能重复。
2. 邮件模板或正文必须存在。
3. 发件邮箱必须存在并可用。
4. 发件域名必须在允许范围内。
5. 必须选择目标人群或策略条件。
6. 发送时间必须符合业务规则。
7. 如果绑定活动,发送时间需要满足活动时间约束。
8. 目标人数需要预估,避免误发全量用户。
目标用户筛选建议包含:
1. 标签包含和标签排除。
2. 站点、产品、品牌、语言、地区。
3. 订阅状态、退订状态、黑名单、投诉用户、永久退信用户。
4. 近期发送频率限制,避免短时间重复触达。
5. 任务级去重,避免同一用户重复生成同一任务邮件。
## 6. 自动 / 实时策略邮件流程
```mermaid
flowchart TD
A["策略配置"] --> B["定时任务生成当日策略任务"]
B --> C["实时策略扫描"]
C --> D["按用户行为和条件筛选"]
D --> E["应用黑名单、退订、频率控制"]
E --> F["生成待发送邮件"]
F --> G["投递发送队列"]
G --> H["发送消费者调用邮件通道"]
H --> I["事件回调更新统计"]
```
策略邮件与批量邮件的区别:
1. 批量邮件通常由运营手动创建,发送时间明确。
2. 策略邮件通常由系统按规则自动生成,可能按分钟或按天扫描。
3. 策略邮件更依赖幂等和频率控制,避免同一用户在同一策略下反复触发。
4. 策略邮件应记录策略 ID、触发原因、触发时间便于归因。
建议策略执行时做并发锁,避免多个任务实例重复生成邮件。
## 7. 邮件发送链路
通用发送链路:
```mermaid
flowchart TD
A["待发送邮件记录"] --> B["写入 Kafka"]
B --> C["发送消费者"]
C --> D["读取发件通道配置"]
D --> E{"发送通道"}
E -->|批量营销| F["AWS SES 或批量发送通道"]
E -->|客服回复| G["SMTP / Gmail / Microsoft"]
F --> H["保存发送结果"]
G --> H
H --> I["通知前端或更新统计"]
```
发送消费者需要处理:
1. 队列消息反序列化。
2. 邮件正文、标题、收件人、发件人、回复地址、附件组装。
3. 发送通道选择。
4. 调用外部服务。
5. 成功后保存 `message_id`、发送时间和成功状态。
6. 失败后保存错误信息、失败状态和重试次数。
发送通道建议按场景区分:
| 场景 | 推荐处理 |
| --- | --- |
| 批量营销邮件 | 走支持批量和事件回调的邮件服务,例如 AWS SES |
| 策略邮件 | 可复用批量发送通道,但必须做频率和幂等控制 |
| 工单客服回复 | 按发件邮箱配置选择 SMTP、Gmail API 或 Microsoft Graph |
| 普通邮箱回复 | 可独立于工单链路,同步或异步发送均可 |
## 8. 邮件事件回调与统计
邮件发送后,外部服务会产生事件。通用事件包括:
| 事件 | 处理建议 |
| --- | --- |
| Delivery / 送达 | 标记邮件已送达,记录送达时间和发送 IP |
| Bounce / 退信 | 区分永久退信和临时退信,更新任务统计;永久退信可加入黑名单 |
| Open / 打开 | 标记打开时间,更新任务打开统计 |
| Click / 点击 | 记录点击链接和点击时间,更新点击统计 |
| Complaint / 投诉 | 记录投诉,加入抑制名单或黑名单 |
| Subscription / 订阅变更 | 更新订阅或退订状态 |
| Reject / 拒信 | 记录拒信原因,更新失败统计 |
| Rendering Failure / 渲染失败 | 记录模板或内容渲染失败 |
| DeliveryDelay / 延迟 | 可记录延迟事件,是否统计需业务确认 |
事件处理要点:
1. 事件必须通过 `message_id` 或自定义追踪 ID 关联到本地邮件记录。
2. 同一事件可能重复回调,需要幂等处理。
3. 打开和点击事件存在图片加载、隐私保护、客户端屏蔽等不确定性,统计只能作为参考指标。
4. 投诉、退订、永久退信应优先进入发送抑制规则。
## 9. 入站邮件 / 表单进入工单流程
入站来源可以有多种:
1. 网站表单提交。
2. 用户真实邮件来信。
3. 外部收信服务回调。
4. IM 或其他渠道转入邮件客服。
通用流程:
```mermaid
flowchart TD
A["用户来信或表单提交"] --> B["入站接收服务"]
B --> C["写入 Kafka 入站队列"]
C --> D["EDM 工单消费者"]
D --> E["保存入站邮件和正文"]
E --> F{"是否存在未关闭工单"}
F -->|否| G["创建新工单"]
F -->|是| H["绑定到原工单并更新未读数"]
G --> I["写入节点日志"]
H --> I
I --> J["通知客服工作台"]
```
创建或更新工单时建议:
1. 以发件邮箱、收件邮箱、业务用户 ID、会话标识等组合判断是否复用未关闭工单。
2. 新工单记录来源、用户邮箱、发件邮箱、团队、状态、未读数、最后来信时间。
3. 已有工单更新最后来信时间、未读数、用户来信数。
4. 如果当前客服离线,可以释放负责人,让工单重新进入分配池。
5. 入站正文应保存原始内容和清洗后的展示内容。
## 10. 工单客服处理流程
### 10.1 工单状态
通用状态建议:
| 状态 | 说明 |
| --- | --- |
| 待处理 | 新入站邮件或表单生成工单,等待客服处理 |
| 服务中 | 客服已接手并正在处理 |
| 未解决 | 客服标记暂未解决,需要后续跟进 |
| 转化中 | 进入销售或转化跟进阶段 |
| 已关闭 | 本次邮件工单处理结束 |
状态值可以由新系统自行定义,但需要保证列表筛选、统计、自动关闭和权限校验口径统一。
### 10.2 自动分配
自动分配建议流程:
1. 找到待处理且未分配的工单。
2. 根据收件邮箱、团队、站点、语言或业务线确定可服务团队。
3. 获取在线客服。
4. 按接单上限、当前处理数、最近分配时间选择客服。
5. 更新工单负责人。
6. 写入分配记录和节点日志。
7. 通知客服工作台。
### 10.3 客服回复
```mermaid
flowchart TD
A["客服点击发送"] --> B["校验客服在线、权限、工单状态"]
B --> C["写入待发送邮件记录和正文"]
C --> D["更新工单未读数、首次响应、回复耗时"]
D --> E["投递客服回复队列"]
E --> F["发送消费者选择 SMTP / Gmail / Microsoft"]
F --> G["保存发送成功或失败结果"]
G --> H["通知客服工作台"]
```
发送前建议校验:
1. 客服必须在线。
2. 工单必须存在且未关闭。
3. 当前客服必须是工单处理人,或具备接手权限。
4. 工单必须属于当前客服可处理团队。
5. 主题、正文、收件人、回复地址必须合法。
6. 附件大小、类型、数量需要符合业务规则和发送通道限制。
### 10.4 转发和主动开工单
转发:
1. 需要填写新的收件人。
2. 转发邮件可以不绑定到原工单作为普通回复。
3. 原邮件和转发邮件需要建立关联,方便追溯。
4. 发送链路仍可复用客服回复队列。
主动开工单:
1. 客服选择发件邮箱和目标用户邮箱。
2. 系统校验发件邮箱归属团队。
3. 如果同一发件邮箱和用户邮箱已有未关闭工单,应拒绝重复创建或要求接手原工单。
4. 创建服务中工单,负责人为当前客服。
5. 写入节点日志和分配记录。
6. 发送第一封邮件。
## 11. 工单辅助任务
新子系统可按需要保留以下后台任务:
| 任务 | 说明 |
| --- | --- |
| 自动分配 | 将未分配待处理工单分配给在线客服 |
| 自动移交 | 当前负责人离线且有新来信时,按代班或团队规则重新分配 |
| DDL 释放 | 工单分配后超过配置时间未处理,释放为未分配 |
| 未回复提醒 | 用户新来信超过配置时间未回复,提醒负责人 |
| 自动关闭 | 服务中工单超过配置时间无新用户来信时自动关闭 |
| 未分配告警 | 未分配工单数量超过阈值时通知团队管理员 |
| 统计同步 | 定时刷新任务发送数、回复数、打开数、点击数等统计 |
具体调度频率和启用范围需要按新系统 SLA 确认。
## 12. 通用限制与风控点
### 12.1 任务和发送限制
建议配置化管理:
1. 单任务最大目标人数。
2. 单轮投递队列数量。
3. 单发件邮箱每分钟、每小时、每天发送上限。
4. 单用户每天或一段时间内最大触达次数。
5. 单域名发送上限。
6. 批量邮件和客服回复是否共享额度。
### 12.2 内容限制
建议校验:
1. 邮件主题最大长度。
2. 正文最小和最大长度。
3. 附件大小、类型、数量。
4. 发件邮箱和回复邮箱格式。
5. 链接合法性和追踪参数。
6. 必要的退订入口和合规声明。
### 12.3 人群抑制
发送前应排除:
1. 退订用户。
2. 投诉用户。
3. 永久退信用户。
4. 风险用户。
5. 明确不允许触达的用户。
6. 已达到频率上限的用户。
### 12.4 幂等和重试
需要幂等的场景:
1. 任务生成邮件记录。
2. 邮件记录投递 Kafka。
3. Kafka 消费发送。
4. 外部事件回调。
5. 入站邮件生成工单。
失败重试建议区分:
1. 可重试:网络超时、临时服务不可用、临时退信、限流。
2. 不可重试:邮箱格式错误、发件权限错误、账号不存在、永久退信、投诉抑制。
## 13. 可观测性
建议至少记录以下指标:
| 指标 | 说明 |
| --- | --- |
| 任务创建数 | 按类型、状态统计 |
| 目标用户数 | 预估人数、实际生成邮件数、过滤人数 |
| 队列积压 | 批量发送队列、客服回复队列、入站队列 |
| 发送成功率 | 按通道、发件邮箱、任务统计 |
| 失败原因分布 | 发送失败、退信、拒信、限流 |
| 送达率、打开率、点击率 | 以事件回调统计,注意打开和点击有误差 |
| 投诉率、退订率 | 作为发送风控核心指标 |
| 工单响应时长 | 首次响应、最近响应、关闭时长 |
| 未分配工单数 | 用于团队容量和告警 |
## 14. 参考代码位置
以下为现有项目中可参考的代码位置,重构时可按新架构重新命名和拆分:
| 模块 | 现有参考 |
| --- | --- |
| 邮件任务后台入口 | `app/admin/controller/MailTaskController.php` |
| 邮件任务服务 | `app/service/MailTaskService.php` |
| 批量邮件生成与投递参考 | `app/service/UserService.php` |
| 批量邮件发送消费者 | `app/command/kafkaConsumer/BatchMailCommand.php` |
| 工单后台入口 | `app/admin/controller/EdmChatController.php` |
| 工单服务 | `app/service/EdmChatService.php` |
| 客服回复消费者 | `app/command/kafkaConsumer/MailSendCommand.php` |
| 表单数据消费者 | `app/command/kafkaConsumer/QaForm.php` |
| 表单创建工单 | `app/service/WebFormDataService.php` |
| 邮件事件回调 | `app/controller/AmazonEmailController.php` |
| 普通邮箱服务 | `app/admin/controller/MailboxController.php``app/service/MailboxService.php` |
| 邮件发送封装 | `app/service/Mail.php` |
| Microsoft 邮件服务 | `app/service/MicrosoftService.php` |
| 策略邮件命令 | `app/command/EdmDoRealTimeStrategy.php``app/command/EdmSendRealTimeStrategy.php``app/command/EdmDayCurrentTask.php` |
| 工单辅助命令 | `app/command/EdmAllocate.php``app/command/EdmMove.php``app/command/EdmDealLine.php``app/command/EdmTimeout.php``app/command/EdmWorkOrderAutoClose.php` |