Files
2026-06-28 19:42:35 +08:00

7.7 KiB

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/

六、进程部署

// config/servers.php
'process' => [
    \Kiri\MailServer\SmtpServerProcess::class,        // 收信 :25
    \Kiri\MailServer\OutboundDeliveryProcess::class,    // 外发投递
],