155 lines
7.7 KiB
Markdown
155 lines
7.7 KiB
Markdown
# kiri-mail-server 架构设计文档
|
|
|
|
## 一、功能概述
|
|
|
|
基于 PHP + Swoole 的生产级邮件服务器。
|
|
|
|
### Phase 1 (已完成): SMTP 收信
|
|
- SMTP 协议接收邮件 (RFC 5321)
|
|
- MIME 邮件解析
|
|
- Maildir 存储
|
|
|
|
### Phase 2 (已完成): 邮件队列与外发投递
|
|
- Redis 持久化发送队列
|
|
- DNS MX 记录查询
|
|
- SMTP 客户端外发投递
|
|
- 指数退避重试策略
|
|
- 死信队列
|
|
- 退信生成
|
|
- 速率限制 (令牌桶)
|
|
|
|
## 二、架构组件
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ SmtpServer │
|
|
│ (Swoole TCP Server :25) │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────┐ ┌────────────┐ ┌───────────────┐ │
|
|
│ │ SmtpSession │ │ MailParser │ │ MaildirStorage │ │
|
|
│ │ (收信会话) │ │ (解析邮件) │ │ (本地存储) │ │
|
|
│ └──────┬──────┘ └────────────┘ └───────────────┘ │
|
|
│ │ │
|
|
│ │ 远程域名 → 入队 │
|
|
│ ▼ │
|
|
│ ┌─────────────────┐ │
|
|
│ │ MailQueue │ │
|
|
│ │ (Redis 持久化队列) │ │
|
|
│ └────────┬────────┘ │
|
|
│ │ │
|
|
└───────────┼────────────────────────────────────────────┘
|
|
│
|
|
┌───────────▼────────────────────────────────────────────┐
|
|
│ OutboundDelivery │
|
|
│ (外发投递进程) │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │
|
|
│ │DnsResolver│ │SmtpClient │ │ RateLimiter │ │
|
|
│ │(MX 查询) │ │(远程投递) │ │ (速率控制) │ │
|
|
│ └──────────┘ └──────────┘ └───────────────┘ │
|
|
│ │
|
|
│ 重试策略: 60s → 300s → 900s → 1800s → 3600s → 死信 │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## 三、邮件投递流程
|
|
|
|
```
|
|
┌──────────┐
|
|
│ SMTP 客户端│
|
|
│ (MUA/MSA) │
|
|
└─────┬─────┘
|
|
│ 连接 :25/:587
|
|
▼
|
|
┌──────────────────┐
|
|
│ SmtpServer │
|
|
│ (接收邮件) │
|
|
└────────┬─────────┘
|
|
│
|
|
┌─────────▼─────────┐
|
|
│ 收件人域名判断 │
|
|
└────┬──────────┬───┘
|
|
│ │
|
|
本地域名 │ │ 远程域名
|
|
▼ ▼
|
|
┌──────────┐ ┌──────────┐
|
|
│ Maildir │ │MailQueue │
|
|
│ 本地存储 │ │Redis 队列 │
|
|
└──────────┘ └────┬─────┘
|
|
│
|
|
▼
|
|
┌────────────────┐
|
|
│OutboundDelivery │
|
|
│ 外发投递进程 │
|
|
└───────┬────────┘
|
|
│
|
|
┌─────────────▼─────────────┐
|
|
│ 投递结果 │
|
|
└──┬──────────┬──────────┬──┘
|
|
│ │ │
|
|
成功 │ 临时失败│ 永久失败│
|
|
▼ ▼ ▼
|
|
┌──────┐ ┌──────┐ ┌──────────┐
|
|
│ 移除 │ │ 重试 │ │ 生成退信 │
|
|
└──────┘ └──────┘ └──────────┘
|
|
```
|
|
|
|
## 四、Redis 数据结构
|
|
|
|
```
|
|
mail:queue:outbound — ZSET, score=下次尝试时间, member=队列ID
|
|
mail:queue:outbound:{id} — Hash, 邮件元数据
|
|
mail:queue:outbound:dead — ZSET, 死信队列
|
|
mail:dns:mx:{domain} — String(JSON), MX 查询缓存 TTL 300s
|
|
mail:ratelimit:global — String(INT), 全局速率计数器
|
|
mail:ratelimit:domain:{d} — String(INT), 域名速率计数器
|
|
```
|
|
|
|
## 五、目录结构
|
|
|
|
```
|
|
kiri-mail-server/
|
|
├── composer.json
|
|
├── DESIGN.md
|
|
├── README.md
|
|
├── config/
|
|
│ └── mail.php
|
|
├── src/
|
|
│ ├── SmtpServer.php # Swoole TCP 服务器 (收信)
|
|
│ ├── SmtpSession.php # SMTP 会话状态机
|
|
│ ├── SmtpProtocol.php # 协议命令解析
|
|
│ ├── SmtpResponse.php # 响应构建器
|
|
│ ├── SmtpClient.php # SMTP 客户端 (发信)
|
|
│ ├── SmtpCommand.php # 命令值对象
|
|
│ ├── SmtpDeliveryResult.php # 投递结果值对象
|
|
│ ├── MailParser.php # MIME 解析
|
|
│ ├── MailMessage.php # 邮件消息
|
|
│ ├── MailQueue.php # Redis 邮件队列
|
|
│ ├── DnsResolver.php # DNS MX 解析
|
|
│ ├── RateLimiter.php # 速率限制器
|
|
│ ├── OutboundDelivery.php # 外发投递调度
|
|
│ ├── OutboundDeliveryProcess.php # 外发投递进程
|
|
│ ├── SmtpServerProcess.php # 收信进程
|
|
│ ├── MailServerProviders.php # Provider
|
|
│ ├── Storage/
|
|
│ │ ├── StorageInterface.php
|
|
│ │ └── MaildirStorage.php
|
|
│ └── Auth/
|
|
│ ├── AuthInterface.php
|
|
│ └── SimpleAuth.php
|
|
└── tests/
|
|
```
|
|
|
|
## 六、进程部署
|
|
|
|
```php
|
|
// config/servers.php
|
|
'process' => [
|
|
\Kiri\MailServer\SmtpServerProcess::class, // 收信 :25
|
|
\Kiri\MailServer\OutboundDeliveryProcess::class, // 外发投递
|
|
],
|
|
```
|