Files
Fulfilled-Knowledge/wishfulfilled-wiki/05_需求文档/通用EDM业务流程说明.md
2026-05-29 14:33:56 +08:00

399 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 通用 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` |