.NET中搭建带Feature Flag的集中式邮件服务实现方案咨询
核心选型判断:独立邮件服务 vs 现有项目内嵌模块
直接按实际业务场景选择即可,没有绝对的最优方案:
- 若当前仅单个业务系统需要发信能力,未来1年无多系统复用邮件能力的规划,直接在现有项目中新增独立类库模块承载邮件能力即可,不需要单独部署独立服务,减少运维成本,代码层做好抽象隔离,后续要拆成独立服务也可以快速平移
- 若已有2个及以上业务系统需要发信,或未来需要统一管理邮件模板、发信频控、黑名单、渠道降级策略,直接新建独立的邮件服务项目,对外提供标准化HTTP/RPC调用接口,所有业务系统统一对接,避免各系统重复实现发信逻辑、规则不统一
.NET 平台落地实现指引
1. 代码分层设计
不管选哪种部署形态,代码层面必须做三层解耦,不要把发信逻辑散落在业务代码里:
- 抽象层:定义
IEmailSender公共接口,约定发信方法的入参规范(包含原始收件人、模板标识、模板变量、附件、发信场景标识等),所有业务逻辑只依赖这个抽象,不耦合具体发信实现 - 核心发信层:实现SMTP、第三方邮件渠道(企业邮、商用邮件推送服务)的实际发信逻辑,内置重试、失败降级能力;所有发信动作全链路留痕,发信时间、原始收件人、邮件内容、发送状态、报错信息全量落库,留存周期按自身合规要求配置
- 规则拦截层:放在发信链路的最前端,所有邮件先经过拦截层的规则校验,再进入实际发信流程,Feature Flag管控、路由覆写逻辑全部在这一层实现
2. Feature Flag 集成实现
直接用.NET官方原生的Microsoft.FeatureManagement库即可,和.NET自带的配置系统、依赖注入容器天然集成,不需要自研开关能力,配置可以直接放在appsettings.json或者统一配置中心,按环境做隔离。需要实现两个核心管控规则:
注意:所有环境的Feature Flag配置必须独立加载,生产环境必须强制关闭所有测试类路由覆写开关,避免规则串漏导致生产邮件发错
- 测试环境路由覆写规则:开启对应开关后,拦截所有外发邮件,把原始收件人信息存入邮件日志的扩展字段,实际收件人替换为当前请求上下文的登录用户邮箱;如果是定时任务、异步后台任务触发的邮件,没有登录用户上下文的,直接fallback到配置里的固定测试邮箱,避免发信失败
- 全局定向收件人规则:开关开启后,不管当前是什么环境、什么业务场景的邮件,全部将收件人替换为配置中指定的固定邮箱,原始收件人信息同步存入日志,一般用于UAT验收、全链路压测场景
配置示例如下:
{ "FeatureManagement": { "EnableTestEnvEmailRedirect": true, // 测试环境设为true,生产环境设为false "EnableGlobalFixedRecipient": false }, "EmailSettings": { "GlobalFixedTestRecipient": "test-list@yourcompany.com", "SmtpServer": "smtp.yourcompany.com", "SmtpPort": 465, "EmailLogRetentionDays": 180 } }
3. 避坑要点
- 所有路由覆写动作必须留痕:邮件日志必须强制记录原始收件人、覆写触发原因(测试环境重定向/全局定向)、实际收件人三个字段,排查问题时可以直接追溯邮件流转逻辑
- 生产环境的Feature Flag修改权限要收归运维/配置管理员,普通开发账号无生产配置修改权限,避免误操作开启重定向规则
- 如果采用独立服务部署形态,要在入口层加签名校验,避免未授权的调用随意发信,同时加发信频控,避免异常流量触发邮件渠道的限流封号
内容的提问来源于stack exchange,提问作者S W
相关产品推荐
相关产品推荐

