# go-mail-system **Repository Path**: louis_xie/go-mail-system ## Basic Information - **Project Name**: go-mail-system - **Description**: go mail system - **Primary Language**: Go - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2025-11-13 - **Last Updated**: 2025-11-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Go 邮件系统扩展版 一个基于Golang构建的高可用、可监控的分布式邮件发送系统。该系统采用主备双提供商(AWS SES + SMTP)、异步重试队列和连接池等技术,确保了邮件投递的可靠性和系统的健壮性。 详细的内容介绍全在微信公众号中。干货持续更新,敬请关注「代码扳手」微信公众号: image ## 系统架构 本系统是一个典型的微服务架构,由多个协作的组件构成: ``` +------------------+ +---------------------+ | | | | | HTTP Client |---->| API Server | | (e.g., curl, web)| | (Gin Framework) | +------------------+ +----------+----------+ | | 调用 v +----------------+-----------+ +--------------------+ | | | | | Mail Service |<---| Worker (Goroutine) | | | | | +------------+-------------+ +---------+----------+ | | +-----------------v--------------+ +----------v-----------+ | | | | | Primary: AWS SES Provider | | Secondary: SMTP Queue| | | | | +--------------------------------+ +----------------------+ | | v v AWS Simple Email Service Redis Stream (Message Queue) ``` ## 核心功能 ### 1. 双重发送提供商 (Dual Providers) 系统实现了主备两种邮件发送路径: - **主提供商 ([SESProvider](internal/mail/provider/ses.go#L14-L17))**: 基于 [AWS SES v2 SDK](https://aws.github.io/aws-sdk-go-v2/docs/service/sesv2/),作为首选发送通道。发送失败时会降级到备用方案。 - **备提供商 ([SMTPProvider](internal/mail/provider/smtp.go#L12-L18))**: 基于Go标准库 `net/smtp`,用于处理来自队列的重试请求,也可在SES初始化失败时作为主要发送通道。 通过 `MailProvider` 接口实现了提供商的抽象,使 `MailService` 能够无缝切换。 ### 2. 异步重试与死信队列 当主提供商(SES)发送失败时,系统不会立即返回错误,而是将邮件请求持久化到消息队列中进行延迟重试。 - **生产者 ([RedisStream.Produce](internal/queue/redis_stream.go#L70-L91))**: `MailService.Send` 方法在SES发送失败后,会调用此方法将序列化的 `MailRequest` 发送到Redis Stream,并设置30分钟的延迟。 - **消费者 ([Worker.Run](internal/worker/worker.go#L35-L69))**: 后台工作协程持续从队列中消费消息,使用SMTP提供商进行重试。 - **智能重试策略**: - 消息会携带 `attempt` 计数器,记录重试次数。 - 达到最大重试次数(默认3次)或遇到永久性错误时,消息会被移动到死信队列(DLQ),防止无限循环。 ### 3. 错误分类与降级 系统对错误进行了精确分类,这是实现智能路由的关键: - **临时性错误 (`*TemporaryError`)**: 如网络超时、服务器繁忙。这类错误会触发降级到队列进行重试。 - **永久性错误 (`*PermanentError`)**: 如邮箱地址不存在、权限被拒。这类错误会直接返回客户端,避免无意义的重试。 错误分类发生在每个提供商的 `SendEmail` 方法内部。 ### 4. 高级特性 - **模板引擎**: 支持使用Go模板语法动态渲染邮件内容,通过 `TemplateRegistry` 注册和管理模板。 - **连接池**: 使用 `ConnectionPool` 限制并发邮件发送的数量,保护下游服务。 - **度量监控**: 集成Prometheus,暴露 `mail_attempts_total`, `mail_success_total` 等指标,可通过 `/metrics` 端点访问。 - **优雅关闭**: 主程序监听SIGINT/SIGTERM信号,能够平滑地停止HTTP服务器和后台工作协程。 ## 快速开始 1. **配置**: 复制 `config/config.yaml.example` 为 `config/config.yaml` 并填写你的AWS和SMTP凭据。 2. **启动**: ```bash go run cmd/main.go ``` 3. **发送邮件**: ```bash curl -X POST http://localhost:8080/send \ -H "Content-Type: application/json" \ -d '{"to": "user@example.com", "subject": "Hello", "body": "

Test email

"}' ``` 4. **查看指标**: 访问 `http://localhost:8080/metrics` 查看Prometheus格式的性能数据。 ## 目录结构 ``` go-mail-system/ ├── cmd/ │ └── main.go # 应用入口,初始化所有组件并启动服务器 ├── config/ │ └── config.yaml # YAML配置文件 ├── internal/ │ ├── api/ # HTTP API 路由 (Gin) │ ├── config/ # 配置加载逻辑 │ ├── mail/ # 邮件核心业务逻辑 │ │ ├── provider/ # 具体的邮件提供商 (SES, SMTP) │ │ ├── service.go # 核心服务,协调各组件 │ │ ├── types.go # 公共数据类型和接口定义 │ │ └── ... │ ├── queue/ # 基于Redis Stream的消息队列实现 │ ├── worker/ # 后台工作协程,负责消费队列 │ └── ... # logging, metrics等 └── go.mod # Go模块定义 ```