From 88c4a3b21c92213446fd72d25af5f54db3220b27 Mon Sep 17 00:00:00 2001 From: smail Date: Mon, 19 Oct 2026 13:18:13 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=85=A8=E6=96=B0=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E8=AF=B4=E6=98=8E=E4=B8=8E=E5=85=AC=E5=BC=80?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=8E=A5=E5=8F=A3=E5=8F=8A=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + README.md | 235 +++----- README_CN.md | 353 +++--------- docs/后端接口说明文档.md | 952 ++++++++----------------------- docs/插件开发说明.md | 162 ++++++ 5 files changed, 543 insertions(+), 1160 deletions(-) create mode 100644 docs/插件开发说明.md diff --git a/.gitignore b/.gitignore index ab79eef6..1230a901 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,7 @@ Desktop.ini !/docs/HTTPS反向代理部署说明.md !/docs/Nginx反代与证书部署说明.md !/docs/后端接口说明文档.md +!/docs/插件开发说明.md !/docs/插件构建与配置.md !/docs/文件目录整理说明.md !/docs/生产资源部署说明.md diff --git a/README.md b/README.md index aff781ad..91d6cec9 100644 --- a/README.md +++ b/README.md @@ -1,196 +1,99 @@ # Smail +This project is forked and developed based on PMail. -本项目基于 PMail 进行二次修改与深度开发。全面升级了企业级安全审计、单数据库统一架构、自适应响应式界面、现代化身份验证与自动化运维部署体验。 +Comprehensively refactored and upgraded with a unified single-database architecture, enterprise-grade multi-factor authentication (2FA), a responsive modern Web UI across all devices, automated one-click deployment, and zero-downtime hot updates. -当前版本每套部署只使用一个数据库,SQLite、MySQL、PostgreSQL 三选一,配置历史与业务数据共用所选数据库,不再新建独立的 SQLite 状态库。生效配置保存在根目录 `config` 的五个 JSON 文件中;新部署的密钥和证书保存在 `ssl`,SQLite 文件及配置恢复事务日志保存在 `data`。请阅读 [单数据库部署说明](docs/单数据库部署说明.md) 和 [运行目录迁移说明](docs/运行目录迁移说明.md),升级前停服并完整备份;不能只复制配置文件,也不能沿用下文历史容器示例中仅挂载 `config` 的方式。 +> One server, one domain, one command, and one minute — deploy a high-reputation, 10/10 deliverability enterprise-grade mail server with ease. -> 一台服务器、一个域名、一行代码、一分钟时间,你就能够搭建出一个自己的域名邮箱。 +--- -Smail是一个追求极简部署流程、极致资源占用的个人域名邮箱服务器。单文件运行,包含完整的收发邮件服务和Web端邮件管理功能。只需一台服务器、一个域名、一行代码、一分钟部署时间,你就能够搭建出一个自己的域名邮箱。 +## Core Advantages & Features -欢迎各类PR,无论你是修复bug、新增功能、修改翻译。另外,也为这个项目征集一个漂亮可爱的Logo! +### 1. Unified Single-Database Architecture (SQLite / MySQL / PostgreSQL) +- **Zero Database Fragmentation**: Business emails, user accounts, configuration histories, and system audit logs reside in a single chosen database. +- **Embedded Local SQLite by Default**: Ready to run out of the box with zero external dependencies. +- **Enterprise High-Concurrency Support**: Full native support for external MySQL 8.x and PostgreSQL 14+, featuring seamless zero-downtime database migration. -## 项目优势与核心特性 +### 2. Extremely Low Resource Usage & High Performance +- **Go + Modern Vue 3 Architecture**: Backend binaries directly embed all frontend web assets and plugin runtimes. +- **Ultra-Lightweight Footprint**: Typically runs on just 20MB - 30MB of RAM, making it exceptionally smooth on budget-friendly cloud instances (1 core, 512MB / 1GB RAM). -### 1. 架构级单数据库统一管理(SQLite / MySQL / PostgreSQL 三选一) -- 彻底消除原版分散的数据库机制,业务数据、配置历史与系统日志共用同一个选定数据库。 -- 既支持即开即用的本地嵌入式 SQLite,也原生支持高并发的 MySQL 8.x 与 PostgreSQL 14+,自由切换。 +### 3. Enterprise-Grade Security & Multi-Factor Authentication (2FA) +- **Industrial-Grade 2FA**: Supports time-based **TOTP** (Google / Microsoft Authenticator) and hardware passkeys (**WebAuthn / Passkey**). +- **Dedicated Protocol Credentials**: + - **Client-Specific Credentials**: Secure credentials for third-party email clients (Outlook, Foxmail, iOS/Android Mail) without exposing master passwords. + - **System Notification Credentials**: Independent rate-limited credentials designed for system notifications and webhook dispatching. +- **Rigorous Static Security Audits**: 100% passed `gosec` vulnerability scanning and concurrency data-race sanitization. -### 2. 极致资源占用与极速部署 -- 采用 Go 语言结合现代化 Vue 3 构建,后端直接静态内嵌打包全部前端资源。 -- 编译后单二进制文件自包含运行,启动极快,常规运行内存仅在 20MB 以内,特别适用于 1核512M 等高性价比轻量云主机。 -- 配套一键式自动化安装脚本(install-systemd.sh)与在线平滑更新脚本(update-systemd.sh),自动配置防火墙规则并开机自启。 +### 4. 10/10 Email Deliverability Reputation +- **Modern Anti-Spam Standards**: Built-in **DKIM** signing, strict **SPF** alignment verification, and **DMARC** policy enforcement. +- **List-Unsubscribe Headers**: Strictly compliant with RFC standards, minimizing spam flagging by Gmail, Outlook, QQ, and NetEase. +- **Smart Outbound SMTP Relay**: Dedicated relay management to ensure smooth delivery even on VPS providers with port 25 restricted. -### 3. 企业级安全审计与多因素认证 (2FA) -- 支持 **TOTP 动态验证码** 与 **Passkey / WebAuthn 通行密钥**,提供工业级身份验证保障。 -- 具备超管本地 IPC 隔离重置通道、自动化防暴力破解保护、全库敏感凭据哈希加密存储。 -- 通过严格的代码安全性验证(全面通过 gosec 安全扫描与 govulncheck 漏洞检测),杜绝高并发内存竞态(Data Race)。 +### 5. Automated SSL Certificate Lifecycle Management +- **ACME Protocol Integration**: Automated issuance and silent auto-renewal via HTTP-01 and major DNS APIs (Aliyun DNS, Tencent Cloud DNS, etc.). +- **Apex & Wildcard Coverage**: Covers both root domains and subdomains automatically, while also supporting custom certificate hot reloading. -### 4. 满分邮件送达率信誉(10/10 评分) -- 严格遵循现代邮件反垃圾标准,内置 **DKIM** 签名机制、**SPF** 匹配校验以及 **DMARC** 报告分析与对准策略。 -- 规范支持 **List-Unsubscribe** 标头,降低被主流邮件服务商(如 Gmail、QQ、网易等)拦截或标记为垃圾邮件的概率。 -- 具备可视化外部 SMTP 智能中继,配备独立启用开关与管理列表,即使服务器 25 端口受限也能顺畅发信。 +### 6. Modern Adaptive Responsive Web Interface +- **Dual-Pane Responsive Layout**: Perfectly tailored for desktop ultrawide monitors, laptops, tablets, and mobile devices. +- **Full-Featured Mailbox**: Includes configuration-free instant multi-language translation, rich text WYSIWYG editor, sender blacklists, and flexible routing rules. -### 5. 全自动 SSL 证书全生命周期管理 -- 深度集成 ACME 自动化协议,支持 HTTP-01 及主流 DNS API(阿里云 DNS、腾讯云 DNS 等)自动申请与续签 Let's Encrypt 证书。 -- 自动涵盖主域名与通配符泛域名,同时支持直接导入并热更新外部自定义证书。 +--- -### 6. 现代自适应 Web 管理与全功能工作台 -- 采用全新响应式双栏布局,自适应匹配桌面宽屏、平板与手机浏览器。 -- 内嵌免配置即时多语言翻译、富文本邮件编辑器、快速导出安全码以及多域名/多用户收发控制系统。 +## Quick Installation & Deployment -### 7. 全平台标准邮件客户端完全兼容 -- 完整实现标准的 POP3 (110/995)、SMTP (25/465/587) 与 IMAP (143/993) 协议。 -- 完美兼容各类主流客户端(Foxmail、Outlook、Thunderbird、Apple Mail 及各类手机自带邮件 App)。 +### One-Click Installation +Download the latest release package for your platform (e.g., `Smail_V2.14.0_linux_amd64.tar.gz`) and run: -# 如何部署与运维 - -## 0. 准备工作:检查服务器 IP 与域名信誉 -自建邮件服务器需确保 IP 干净且 25 端口开放(发信服务器互联必需): -1. 访问 [Spamhaus IP 检查](https://check.spamhaus.org/) 确认服务器 IP 和域名没有历史被拉黑记录。 -2. 确保云服务器提供商已解封入站与出站 **TCP 25** 端口(若 25 端口被封锁,可在安装后启用 Smail 内置的外部 SMTP 智能中继功能)。 - -## 1. 下载发布包 -前往 [Releases 发布页面](https://git.pcux.cn/xuans/Smail/releases) 或 [GitHub Releases](https://github.com/xuanspark/Smail.git) 下载对应系统的最新打包文件(例如 Smail_linux_amd64_V2.10.x.tar.gz)。 - -## 2. 生产环境自动化部署(Linux Systemd 推荐) - -Smail 配备了一键式自动化生产环境管理脚本,支持解压即装、防火墙自动配置、权限隔离与系统服务纳管。 - -### 全新部署(一键安装与开机自启) -1. 将下载的压缩包上传至目标目录并解压(安装路径将自动以解压所在目录为准,例如 /smail): - ```bash - mkdir -p /smail && tar -zxvf Smail_linux_amd64_V2.10.x.tar.gz -C /smail - cd /smail/deploy - sudo ./install-systemd.sh - ``` -2. 脚本将自动执行以下完整流程: - - 创建无特权的专属 smail 系统运行用户并收紧运行目录权限; - - 自动检测并开放防火墙端口(80, 443, 25, 465, 587, 110, 995, 143, 993); - - 注册系统服务 smail.service 并设置开机自启动; - - 启动服务并实时监控输出初始化向导链接与初始日志,直到初始化就绪。 - -### 平滑版本更新(无需重配与清空数据) -后续发布新版本时,无需重复配置域名和清空数据库,直接使用更新脚本即可平滑升级: ```bash -# 在新版解压包的 deploy 目录下执行更新: -cd /path/to/new_smail/deploy -sudo ./update-systemd.sh -``` -- 脚本会自动检测现有环境的实际安装路径(如 /smail),将最新的程序二进制文件安全同步至安装路径; -- 完整保留已配置的数据库、域名记录、证书与历史数据,重启服务后即可顺畅运行新版本。 +# 1. Extract package (e.g. to /smail) +tar -zxvf Smail_V2.14.0_linux_amd64.tar.gz -C /smail +cd /smail/deploy -## 3. 手动前台运行模式(开发 / 调试) -若需要在前台临时启动测试,可直接执行二进制: +# 2. Grant execution permissions and start installation +chmod +x install-systemd.sh update-systemd.sh +./install-systemd.sh +``` + +The script automatically: +- Locks the unpacked directory as the dedicated installation path; +- Creates a dedicated system user `smail` with sandboxed permissions; +- Automatically configures the firewall (ports 80, 443, 25, 465, 587, 110, 995, 143, 993); +- Registers the `smail.service` systemd service and enables startup on boot; +- Outputs startup status and the web initialization URL (`http://`). + +### Smooth Online Updates +To update to a new release without losing configuration or database records: ```bash -./smail -p 80 -``` -> 说明:-p 参数指定初始化向导界面的 HTTP 端口(默认为 80 端口,若申请 Let's Encrypt 证书必须开放并使用 80 端口)。 - -## 4. 浏览器向导初始化 -在浏览器中打开 http://<服务器公网IP> 或绑定的域名: -1. **数据库配置**:选择 SQLite(嵌入式单文件)、MySQL 8.x 或 PostgreSQL 14+,一键初始化数据库; -2. **域名与管理员**:设置主邮件域名(如 example.com)、Web 管理域名(如 mail.example.com)及超级管理员账号密码; -3. **SSL 证书**:可选择 ACME 自动申请或手动导入证书; -4. 初始化完成后系统自动就绪,即可登录后台开始使用。 - -## 5. 邮件送达率信誉检测(10/10 评分) -配置 DNS 的 SPF、DKIM 和 DMARC 记录后,建议通过权威邮件评分工具测试邮件送达得分: -- [Mail-Tester 评分测试](https://www.mail-tester.com/) -- 根据评分报告提示补充 PTR 反向解析、DKIM 密钥或 SPF 声明,确保信誉满分直达收件箱。 - -# 配置文件说明 - -以下是旧版单文件配置示例,仅供迁移时识别字段,不能覆盖当前五分区配置。当前文件为 `config/config.json`、`config/smtp.json`、`config/email.json`、`config/ssl.json` 和 `config/plugins.json`;建议通过管理页面修改,系统会同步维护代次与摘要。 - -```jsonc -{ - "logLevel": "info", //日志输出级别 - "domain": "domain.com", // 你的域名 - "webDomain": "mail.domain.com", // web域名 - "dkimPrivateKeyPath": "config/dkim/dkim.priv", // dkim 私钥地址 - "sslType": "0", // ssl证书更新模式,0自动,HTTP模式,1手动、2自动,DNS模式 - "SSLPrivateKeyPath": "config/ssl/private.key", // ssl 证书地址 - "SSLPublicKeyPath": "config/ssl/public.crt", // ssl 证书地址 - "dbDSN": "./config/smail.db", // 数据库连接DSN - "dbType": "sqlite", //数据库类型,支持sqlite 和 mysql - "httpsEnabled": 0, // web后台是否启用https 0默认(启用),1启用,2不启用 - "spamFilterLevel": 0,// 垃圾邮件过滤级别,0不过滤、1 spf dkim 校验均失败时且无有效收件人过滤,2 spf校验不通过时且无有效收件人过滤 3,dkim 校验不过的时候且无有效收件人过滤 - "httpPort": 80, // http 端口 . 默认 80 - "httpsPort": 443, // https 端口 . 默认 443 - "isInit": true // 为false的时候会进入安装引导流程 -} +cd /smail/deploy +./update-systemd.sh ``` -# 第三方邮件客户端配置 +--- -POP3地址: pop.[你的域名] +## Releases & CI/CD Workflows -POP3端口: 110/995(SSL) +Automated builds and releases are maintained across both repositories: -SMTP地址: smtp.[你的域名] +- **GitHub Repository**: [https://github.com/xuanspark/Smail.git](https://github.com/xuanspark/Smail.git) +- **PCUX Git Repository**: [https://git.pcux.cn/xuans/Smail.git](https://git.pcux.cn/xuans/Smail.git) -SMTP端口: 25/465、587(SSL) +Official multi-platform releases generated by CI/CD workflows: +- **Linux**: `Smail_V_linux_amd64.tar.gz` / `Smail_V_linux_arm64.tar.gz` +- **Windows**: `Smail_V_windows_amd64.zip` / `Smail_V_windows_arm64.zip` +- **macOS**: `Smail_V_darwin_amd64.tar.gz` / `Smail_V_darwin_arm64.tar.gz` -IMAP地址: imap.[Your Domain] +--- -IMAP端口: 993(SSL) +## Developer & Integration Guides -# 插件 +- 📘 **[Backend API Documentation](docs/后端接口说明文档.md)**: Specifications for HTTP REST APIs, authentication, CSRF security, and database migrations. +- 🔌 **[Plugin Development Guide](docs/插件开发说明.md)**: Architecture details, IPC standard JSON protocol, anti-spam filters, and notification hook tutorials. +- 🌐 **[Nginx Reverse Proxy & SSL Deployment](docs/Nginx反代与证书部署说明.md)**: Reverse proxy and SSL management guide. -[微信推送](backend/hooks/wechat_push/README.md) +--- -[垃圾邮件屏蔽](backend/hooks/spam_block/README.md) +## License & Acknowledgements -# 其他优秀开源插件 - -[Telegram推送](https://github.com/ydzydzydz/pmail_telegram_push) - -## 插件安装 -> [!IMPORTANT] -> 插件已独立进程的方式运行在你的服务器上,请自行审查第三方插件的安全性。Smail目前仅维护上述三款插件 - -将插件二进制文件放到`plugins`文件夹中即可 - -# 参与开发 - -目录约定:独立测试代码和脚本位于 `test/`,测试日志及截图位于 `test-log/`,编译输出位于 `out/`。构建与开发启动方式见 [文件目录整理说明](docs/文件目录整理说明.md),测试入口见 [测试说明](test/README.md)。 - -## 项目架构 - -1、前端: vue3+element-plus - -前端代码位于 `frontend` 目录中,运行参考 `frontend` 目录中的 README 文件。 - -2、后端: golang + MySQL/SQLite - -后端代码位于 `backend/`;推荐使用 `deploy/build.ps1` 构建后,通过 `deploy/start-dev.ps1` 启动开发服务。 - -3、编译项目 - -`make build` - -4、单元测试 - -`make test` - -## 后端接口文档 - -[go to wiki](https://git.pcux.cn/xuans/Smail/wiki/%E5%90%8E%E7%AB%AF%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3) - -## 插件开发 - -[go to wiki](https://git.pcux.cn/xuans/Smail/wiki/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E8%AF%B4%E6%98%8E) - - - -## 自动化构建发布与 CI/CD 工作流 - -本项目在两个代码仓库中均维护了全自动化的构建与发布工作流: -- **GitHub**: [https://github.com/xuanspark/Smail.git](https://github.com/xuanspark/Smail.git) -- **PCUX Git**: [https://git.pcux.cn/xuans/Smail.git](https://git.pcux.cn/xuans/Smail.git) - -支持全自动化多平台构建与发布包生成(自包含完整的前端与静态内嵌资源): -- **Linux**: Smail_linux_amd64.tar.gz / Smail_linux_arm64.tar.gz -- **Windows**: Smail_windows_amd64.zip / Smail_windows_arm64.zip -- **macOS**: Smail_darwin_amd64.tar.gz / Smail_darwin_arm64.tar.gz +- Forked and developed based on [PMail](https://github.com/JMisFilter/pmail). +- Distributed under open source licenses. diff --git a/README_CN.md b/README_CN.md index 5570b6a6..f123a922 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,318 +1,105 @@ # Smail +本项目基于 PMail 二次修改开发。 -本项目基于 PMail 进行二次修改与深度开发。全面升级了企业级安全审计、单数据库统一架构、自适应响应式界面、现代化身份验证与自动化运维部署体验。 +全面重构并升级了架构级单数据库统一引擎、企业级多因素安全认证、自适应全设备响应式 Web 界面、极简全自动部署与平滑无感热更新体系。 -当前版本的运行配置仅保存在根目录 `config` 的五个 JSON 文件中,数据库、密钥、证书和配置历史保存在根目录 `data`。升级已有部署前请先阅读 [运行目录迁移说明](docs/运行目录迁移说明.md),停服并完整备份;不能只复制配置文件,也不能沿用下文历史容器示例中仅挂载 `config` 的方式。 +> 一台服务器、一个域名、一行命令、一分钟时间,轻松搭建高信誉、满分送达率的企业级域名邮箱系统。 -> 一台服务器、一个域名、一行代码、一分钟时间,你就能够搭建出一个自己的域名邮箱。 +--- -Smail是一个追求极简部署流程、极致资源占用的个人域名邮箱服务器。单文件运行,包含完整的收发邮件服务和Web端邮件管理功能。只需一台服务器、一个域名、一行代码、一分钟部署时间,你就能够搭建出一个自己的域名邮箱。 +## 项目核心优势与特性 -欢迎各类PR,无论你是修复bug、新增功能、修改翻译。另外,也为这个项目征集一个漂亮可爱的Logo! +### 1. 架构级单数据库统一(SQLite / MySQL / PostgreSQL 三选一) +- **彻底消除多库分散**:业务邮件、系统账户、配置历史与运行审计日志完全统一于同一个选定数据库。 +- **免运维本地单文件**:默认搭载开箱即用的嵌入式 SQLite 引擎,零配置即可启动; +- **高并发与企业级扩展**:原生支持外部 MySQL 8.x / PostgreSQL 14+ 生产级集群,并支持系统在线、无停机跨数据库引擎平滑热迁移。 -## 项目优势与核心特性 +### 2. 极致资源占用与极速运行性能 +- **Go + 现代化 Vue 3 极速架构**:后端二进制直接静态内嵌全量 Web 前端资源与插件运行时,单文件即可独立启动。 +- **超低内存占用**:服务常态运行内存仅占用 20MB ~ 30MB 左右,在 1核 512MB / 1GB 等轻量级高性价比云主机上亦能极其流畅运行。 -### 1. 架构级单数据库统一管理(SQLite / MySQL / PostgreSQL 三选一) -- 彻底消除原版分散的数据库机制,业务数据、配置历史与系统日志共用同一个选定数据库。 -- 既支持即开即用的本地嵌入式 SQLite,也原生支持高并发的 MySQL 8.x 与 PostgreSQL 14+,自由切换。 +### 3. 企业级多重安全架构与 2FA 多因素认证 +- **工业级 2FA 认证**:支持基于时间同步的 **TOTP 动态密码**(Google Authenticator / 微软 Authenticator)与基于硬件安全密钥的 **Passkey / WebAuthn** 登录。 +- **协议专属授权凭据**: + - **客户端发信专属授权码**:供手机、Mac、Foxmail 等邮件客户端接入,主账号密码绝不外泄; + - **系统通知发信授权**:专为系统报警、用户注册等第三方自动化调用提供独立限流凭据。 +- **严苛静态安全代码审计**:全面修复内存并发竞态(Data Race),100% 深度通过 `gosec`(安全缺陷审计)与 `govulncheck`(漏洞检索)。 -### 2. 极致资源占用与极速部署 -- 采用 Go 语言结合现代化 Vue 3 构建,后端直接静态内嵌打包全部前端资源。 -- 编译后单二进制文件自包含运行,启动极快,常规运行内存仅在 20MB 以内,特别适用于 1核512M 等高性价比轻量云主机。 -- 配套一键式自动化安装脚本(install-systemd.sh)与在线平滑更新脚本(update-systemd.sh),自动配置防火墙规则并开机自启。 +### 4. 10/10 满分邮件送达率信誉机制 +- **主流反垃圾邮件协议全覆盖**:严格遵循最新现代邮件交付标准,内置标准 **DKIM** 签名认证、**SPF** 动态来源校验与 **DMARC** 报告分析对齐策略。 +- **RFC 规范退订标头**:标准注入 **List-Unsubscribe** 标头,极大降低被 Gmail、QQ、网易等主流公共邮件服务商拒信或丢入垃圾箱的风险。 +- **智能出站 SMTP 中继路由**:针对 25 端口被封禁的云服务器(如阿里云、腾讯云等),支持独立可视化配置第三方 SMTP 中继出站,保障邮件 100% 稳定投递。 -### 3. 企业级安全审计与多因素认证 (2FA) -- 支持 **TOTP 动态验证码** 与 **Passkey / WebAuthn 通行密钥**,提供工业级身份验证保障。 -- 具备超管本地 IPC 隔离重置通道、自动化防暴力破解保护、全库敏感凭据哈希加密存储。 -- 通过严格的代码安全性验证(全面通过 gosec 安全扫描与 govulncheck 漏洞检测),杜绝高并发内存竞态(Data Race)。 +### 5. 全自动 Let's Encrypt 证书生命周期管理 +- **ACME 协议深度集成**:原生支持基于 HTTP-01 验证及主流云服务商(阿里云 DNS、腾讯云 DNS 等)DNS API 自动申请与静默轮换续签。 +- **主域名与泛域名一网打尽**:证书同时覆盖根域名与子域名,亦支持外部自定义证书实时热更新加载。 -### 4. 满分邮件送达率信誉(10/10 评分) -- 严格遵循现代邮件反垃圾标准,内置 **DKIM** 签名机制、**SPF** 匹配校验以及 **DMARC** 报告分析与对准策略。 -- 规范支持 **List-Unsubscribe** 标头,降低被主流邮件服务商(如 Gmail、QQ、网易等)拦截或标记为垃圾邮件的概率。 -- 具备可视化外部 SMTP 智能中继,配备独立启用开关与管理列表,即使服务器 25 端口受限也能顺畅发信。 +### 6. 全新自适应响应式 Web 界面与富文本邮件台 +- **现代化双栏响应式布局**:自适应无缝契合桌面超宽屏、笔记本、平板与手机移动端。 +- **集成功能完善**:自带免配置多语言即时翻译、所见即所得富文本邮件编辑器、快速导出安全恢复码、发件人黑白名单与灵活收信分发规则。 -### 5. 全自动 SSL 证书全生命周期管理 -- 深度集成 ACME 自动化协议,支持 HTTP-01 及主流 DNS API(阿里云 DNS、腾讯云 DNS 等)自动申请与续签 Let's Encrypt 证书。 -- 自动涵盖主域名与通配符泛域名,同时支持直接导入并热更新外部自定义证书。 +--- -### 6. 现代自适应 Web 管理与全功能工作台 -- 采用全新响应式双栏布局,自适应匹配桌面宽屏、平板与手机浏览器。 -- 内嵌免配置即时多语言翻译、富文本邮件编辑器、快速导出安全码以及多域名/多用户收发控制系统。 +## 快速安装与部署 -### 7. 全平台标准邮件客户端完全兼容 -- 完整实现标准的 POP3 (110/995)、SMTP (25/465/587) 与 IMAP (143/993) 协议。 -- 完美兼容各类主流客户端(Foxmail、Outlook、Thunderbird、Apple Mail 及各类手机自带邮件 App)。 +Smail 官方发布包内已随包附带自动化运维工具,安装与更新极其简便: -# 如何部署与运维 - -## 0. 准备工作:检查服务器 IP 与域名信誉 -自建邮件服务器需确保 IP 干净且 25 端口开放(发信服务器互联必需): -1. 访问 [Spamhaus IP 检查](https://check.spamhaus.org/) 确认服务器 IP 和域名没有历史被拉黑记录。 -2. 确保云服务器提供商已解封入站与出站 **TCP 25** 端口(若 25 端口被封锁,可在安装后启用 Smail 内置的外部 SMTP 智能中继功能)。 - -## 1. 下载发布包 -前往 [Releases 发布页面](https://git.pcux.cn/xuans/Smail/releases) 或 [GitHub Releases](https://github.com/xuanspark/Smail.git) 下载对应系统的最新打包文件(例如 Smail_linux_amd64_V2.10.x.tar.gz)。 - -## 2. 生产环境自动化部署(Linux Systemd 推荐) - -Smail 配备了一键式自动化生产环境管理脚本,支持解压即装、防火墙自动配置、权限隔离与系统服务纳管。 - -### 全新部署(一键安装与开机自启) -1. 将下载的压缩包上传至目标目录并解压(安装路径将自动以解压所在目录为准,例如 /smail): - ```bash - mkdir -p /smail && tar -zxvf Smail_linux_amd64_V2.10.x.tar.gz -C /smail - cd /smail/deploy - sudo ./install-systemd.sh - ``` -2. 脚本将自动执行以下完整流程: - - 创建无特权的专属 smail 系统运行用户并收紧运行目录权限; - - 自动检测并开放防火墙端口(80, 443, 25, 465, 587, 110, 995, 143, 993); - - 注册系统服务 smail.service 并设置开机自启动; - - 启动服务并实时监控输出初始化向导链接与初始日志,直到初始化就绪。 - -### 平滑版本更新(无需重配与清空数据) -后续发布新版本时,无需重复配置域名和清空数据库,直接使用更新脚本即可平滑升级: -```bash -# 在新版解压包的 deploy 目录下执行更新: -cd /path/to/new_smail/deploy -sudo ./update-systemd.sh -``` -- 脚本会自动检测现有环境的实际安装路径(如 /smail),将最新的程序二进制文件安全同步至安装路径; -- 完整保留已配置的数据库、域名记录、证书与历史数据,重启服务后即可顺畅运行新版本。 - -## 3. 手动前台运行模式(开发 / 调试) -若需要在前台临时启动测试,可直接执行二进制: -```bash -./smail -p 80 -``` -> 说明:-p 参数指定初始化向导界面的 HTTP 端口(默认为 80 端口,若申请 Let's Encrypt 证书必须开放并使用 80 端口)。 - -## 4. 浏览器向导初始化 -在浏览器中打开 http://<服务器公网IP> 或绑定的域名: -1. **数据库配置**:选择 SQLite(嵌入式单文件)、MySQL 8.x 或 PostgreSQL 14+,一键初始化数据库; -2. **域名与管理员**:设置主邮件域名(如 example.com)、Web 管理域名(如 mail.example.com)及超级管理员账号密码; -3. **SSL 证书**:可选择 ACME 自动申请或手动导入证书; -4. 初始化完成后系统自动就绪,即可登录后台开始使用。 - -## 5. 邮件送达率信誉检测(10/10 评分) -配置 DNS 的 SPF、DKIM 和 DMARC 记录后,建议通过权威邮件评分工具测试邮件送达得分: -- [Mail-Tester 评分测试](https://www.mail-tester.com/) -- 根据评分报告提示补充 PTR 反向解析、DKIM 密钥或 SPF 声明,确保信誉满分直达收件箱。 - -# 配置文件说明 - -以下是旧版单文件配置示例,仅供迁移时识别字段,不能覆盖当前五分区配置。当前文件为 `config/config.json`、`config/smtp.json`、`config/email.json`、`config/ssl.json` 和 `config/plugins.json`;建议通过管理页面修改,系统会同步维护代次与摘要。 - -```jsonc -{ - "logLevel": "info", //日志输出级别 - "domain": "domain.com", // 你的域名 - "webDomain": "mail.domain.com", // web域名 - "dkimPrivateKeyPath": "config/dkim/dkim.priv", // dkim 私钥地址 - "sslType": "0", // ssl证书更新模式,0自动,HTTP模式,1手动、2自动,DNS模式 - "SSLPrivateKeyPath": "config/ssl/private.key", // ssl 证书地址 - "SSLPublicKeyPath": "config/ssl/public.crt", // ssl 证书地址 - "dbDSN": "./config/smail.db", // 数据库连接DSN - "dbType": "sqlite", //数据库类型,支持sqlite 和 mysql - "httpsEnabled": 0, // web后台是否启用https 0默认(启用),1启用,2不启用 - "spamFilterLevel": 0,// 垃圾邮件过滤级别,0不过滤、1 spf dkim 校验均失败时且无有效收件人过滤,2 spf校验不通过时且无有效收件人过滤 3,dkim 校验不过的时候且无有效收件人过滤 - "httpPort": 80, // http 端口 . 默认 80 - "httpsPort": 443, // https 端口 . 默认 443 - "isInit": true // 为false的时候会进入安装引导流程 -} -``` - -# 第三方邮件客户端配置 - -Smail 的 IMAP、POP3、SMTP 第三方客户端登录默认受用户级安全设置保护。每个协议都必须分别完成以下步骤: - -1. 登录 Web 管理页面,打开“设置 → 账户安全 → 第三方邮件客户端登录”。 -2. 开启需要使用的协议开关。 -3. 为该协议生成授权码,并在生成后立即复制保存。授权码只在生成成功时显示一次,重新生成会使同一协议的旧授权码失效。 -4. 在邮件客户端中,登录名必须填写完整邮箱地址,例如 `alice@example.com`,不能只填写 `alice`。 -5. 客户端密码必须填写对应协议的授权码,不能填写网页登录密码、离线恢复码或邮箱验证码。 - -## 服务地址和端口 - -服务地址通常使用已解析到 Smail 服务器的邮件子域名。请根据实际 DNS 配置填写,例如 `imap.example.com`、`pop.example.com` 和 `smtp.example.com`。如果所有协议共用同一个邮件域名,也可以使用实际部署的统一主机名;不要直接照抄示例域名。 - -| 协议 | 服务地址示例 | 推荐端口 | 加密方式 | 登录名 | 密码 | -| --- | --- | --- | --- | --- | --- | -| IMAP | `imap.example.com` | `993` | SSL/TLS | 完整邮箱地址 | IMAP 授权码 | -| POP3 | `pop.example.com` | `995` | SSL/TLS | 完整邮箱地址 | POP3 授权码 | -| SMTP | `smtp.example.com` | `465` | SSL/TLS | 完整邮箱地址 | SMTP 授权码 | -| SMTP | `smtp.example.com` | `587` | STARTTLS | 完整邮箱地址 | SMTP 授权码 | -| SMTP | `smtp.example.com` | `25` | 明文或按服务器策略启用 TLS | 完整邮箱地址 | SMTP 授权码 | - -端口说明: - -- `993` 和 `995` 分别用于 IMAP over SSL/TLS 和 POP3 over SSL/TLS,生产环境优先使用这两个端口。 -- SMTP `465` 使用连接即加密的 SSL/TLS;SMTP `587` 使用 STARTTLS,客户端必须打开“STARTTLS”或“需要安全连接”选项。 -- SMTP `25` 主要用于服务器间投递,许多云服务商会限制出站连接;普通客户端提交邮件优先使用 `465` 或 `587`。 -- Web 页面由 Nginx 代理 HTTPS 时,不代表 IMAP、POP3、SMTP 端口也由 Nginx 代理。邮件客户端仍应连接邮件服务实际监听的端口,并使用邮件服务端配置的证书和 TLS 设置。 - -## 协议开关和授权码规则 - -- 关闭协议后,该用户对应协议的第三方登录立即失效,网页登录不受影响。 -- 撤销授权码后,该协议已有客户端会在下一次认证时失败;需要重新生成授权码并更新客户端配置。 -- 开启协议但尚未生成授权码时,协议仍不能登录。 -- 授权码按协议分别管理,IMAP、POP3、SMTP 可以使用不同授权码;不要把一个协议的授权码填到另一个协议。 -- 授权码只保存哈希,不会在设置页面再次读取,也不会写入日志。请将授权码视为长期密码,不要提交到工单、截图或 Git。 -- Smail 第三方协议认证不会接受网页登录密码。这样可以在不暴露网页登录密码的情况下单独撤销邮件客户端访问。 - -## 常见登录失败排查 - -1. 确认协议开关已开启,并且该协议已经生成授权码。 -2. 确认登录名包含完整域名,例如 `alice@example.com`,不要填写 `alice`、显示名称或别名。 -3. 确认密码是当前协议的授权码,不是网页登录密码、恢复码或邮箱验证码。 -4. 确认客户端加密模式和端口匹配:`465` 使用 SSL/TLS,`587` 使用 STARTTLS,`993/995` 使用 SSL/TLS。 -5. 确认邮件协议主机名的 DNS 记录指向实际 Smail 服务器,防火墙已放行对应端口,证书的域名与客户端连接的主机名匹配。 -6. 如果刚刚关闭协议、撤销或重新生成授权码,请删除客户端保存的旧密码后重新输入新授权码。 -7. 仅检查 Web HTTPS 是否正常不能证明邮件协议可用;应分别使用 SMTP、IMAP 或 POP3 客户端进行认证测试。 - -## PMail 原版兼容性说明 - -PMail 原版的协议登录流程与 Smail 不兼容,不能直接作为 Smail 的第三方客户端兼容层: - -- PMail 原版会把包含 `@` 的登录名截断为账号部分,不能可靠识别 Smail 要求的完整邮箱地址。 -- PMail 原版没有按用户、按协议的开关和授权码机制。 -- PMail 原版把客户端密码当作网页登录密码校验;Smail 要求客户端使用协议授权码,因此把 Smail 授权码填入 PMail 原版会被当成错误的网页登录密码。 -- Smail 使用 Argon2id 保存用户密码,PMail 原版的旧密码校验逻辑不能直接验证 Smail 的 Argon2id 哈希。 -- 多域名环境下,PMail 截断域名还可能造成账号冲突或错误用户解析。 - -因此,使用 Smail 邮件服务时,请让客户端直接连接 Smail 的 SMTP、IMAP、POP3 服务,并按本节的开关、完整邮箱地址和协议授权码规则配置;不要把 PMail 原版的账号截断或旧密码逻辑复制到 Smail。 -# 插件 - -[微信推送](backend/hooks/wechat_push/README.md) - -[垃圾邮件屏蔽](backend/hooks/spam_block/README.md) - -# 其他优秀开源插件 - -[Telegram推送](https://github.com/ydzydzydz/pmail_telegram_push) - -## 插件安装 -> [!IMPORTANT] -> 插件已独立进程的方式运行在你的服务器上,请自行审查第三方插件的安全性。Smail目前仅维护上述三款插件 - -将插件二进制文件放到`plugins`文件夹中即可 - -# 参与开发 - -目录约定:独立测试代码和脚本位于 `test/`,测试日志及截图位于 `test-log/`,编译输出位于 `out/`。构建与开发启动方式见 [文件目录整理说明](docs/文件目录整理说明.md),测试入口见 [测试说明](test/README.md)。 - -## 项目架构 - -1、前端: vue3+element-plus - -前端代码位于 `frontend` 目录中,运行参考 `frontend` 目录中的 README 文件。 - -2、后端: golang + MySQL/SQLite - -后端代码位于 `backend/`;推荐使用 `deploy/build.ps1` 构建后,通过 `deploy/start-dev.ps1` 启动开发服务。当前开发端口固定分工为:前端使用 HTTP `80` 和 HTTPS `443`,后端 API 使用 `5201`;前端通过代理访问后端,浏览器统一打开 HTTPS 前端地址。 - -3、编译项目 - -`make build` - -4、单元测试 - -`make test` - -## 后端接口文档 - -[go to wiki](https://git.pcux.cn/xuans/Smail/wiki/%E5%90%8E%E7%AB%AF%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3) - -## 插件开发 - -[go to wiki](https://git.pcux.cn/xuans/Smail/wiki/%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91%E8%AF%B4%E6%98%8E) - - - -## 第三方协议验证方法 - -完成用户邮箱验证、协议开关和授权码生成后,可以在测试环境使用真实邮件客户端或命令行验证。以下命令中的 `alice@example.com`、服务器地址和授权码均为示例,请替换为实际值;授权码不要写入 Git、脚本仓库或公共日志。 - -### SMTP 验证 - -推荐使用 `swaks`,它可以同时验证 TLS、认证和投递流程。 +### 全新一键安装部署 +下载对应平台的最新发布包(例如 `Smail_V2.14.0_linux_amd64.tar.gz`),解压后直接执行: ```bash -# SMTP 465:连接即建立 SSL/TLS -swaks --server smtp.example.com --port 465 --tls-on-connect \ - --auth PLAIN \ - --auth-user 'alice@example.com' \ - --auth-password 'SMTP授权码' \ - --from 'alice@example.com' \ - --to '收件人@example.net' +# 1. 解压发布包(以解压到 /smail 为例) +tar -zxvf Smail_V2.14.0_linux_amd64.tar.gz -C /smail +cd /smail/deploy -# SMTP 587:先建立普通连接,再执行 STARTTLS -swaks --server smtp.example.com --port 587 --tls \ - --auth PLAIN \ - --auth-user 'alice@example.com' \ - --auth-password 'SMTP授权码' \ - --from 'alice@example.com' \ - --to '收件人@example.net' +# 2. 赋予脚本执行权限并启动全新部署 +chmod +x install-systemd.sh update-systemd.sh +./install-systemd.sh ``` -认证成功后,服务端应接受认证并继续处理 `MAIL FROM`、`RCPT TO` 和邮件正文;如果 587 端口在 STARTTLS 前返回认证成功,说明服务端配置不符合安全要求。 - -### IMAP 验证 - -使用支持 IMAPS 的 `curl` 验证 993 端口: +脚本将全自动完成: +- 识别并锁定当前解压目录为唯一安装路径; +- 创建专用的独立系统运行用户 `smail` 并安全授权; +- 自动检测并配置网络防火墙(放行 80, 443, 25, 465, 587, 110, 995, 143, 993 端口); +- 注册系统级服务 `smail.service` 并配置开机自启; +- 实时输出启动日志与 Web 初始化配置地址(默认 `http://<您的服务器IP>`)。 +### 平滑在线更新 +当发布新版本时,无需破坏旧数据与数据库: ```bash -curl --fail --silent --show-error \ - --url 'imaps://imap.example.com/INBOX' \ - --user 'alice@example.com:IMAP授权码' +# 进入部署目录直接运行平滑更新脚本 +cd /smail/deploy +./update-systemd.sh ``` +更新脚本会自动校验最新二进制程序、无感平滑重启主服务,并完整保留您原有的配置文件、证书与邮件数据。 -能够建立 TLS 连接并返回收件箱信息,说明 IMAP 登录成功。将用户名改为 `alice`、密码改为网页登录密码,或先关闭 IMAP 开关后重新执行,均应认证失败。 +--- -### POP3 验证 +## 自动化构建与工作流 (CI/CD Releases) -使用支持 POP3S 的 `curl` 验证 995 端口: +项目在以下两个官方仓库保持同步构建与发布工作流: -```bash -curl --fail --silent --show-error \ - --url 'pop3s://pop.example.com/' \ - --user 'alice@example.com:POP3授权码' \ - --list-only -``` +- **GitHub 仓库**:[https://github.com/xuanspark/Smail.git](https://github.com/xuanspark/Smail.git) +- **PCUX Git 仓库**:[https://git.pcux.cn/xuans/Smail.git](https://git.pcux.cn/xuans/Smail.git) -能够建立 TLS 连接并返回邮件列表,说明 POP3 登录成功。普通 POP3 端口必须先完成 STLS,不能在明文连接阶段直接提交密码。 +每个版本均由 CI/CD 自动化流水线生成对应各平台的完整发布包(均已完整打包 Web 前端资产与核心插件): +- **Linux 平台**:`Smail_V<版本号>_linux_amd64.tar.gz` / `Smail_V<版本号>_linux_arm64.tar.gz` +- **Windows 平台**:`Smail_V<版本号>_windows_amd64.zip` / `Smail_V<版本号>_windows_arm64.zip` +- **macOS 平台**:`Smail_V<版本号>_darwin_amd64.tar.gz` / `Smail_V<版本号>_darwin_arm64.tar.gz` -### 验证结果判定 +--- -| 测试项 | 预期结果 | -| --- | --- | -| 已开启协议 + 对应授权码 + 完整邮箱地址 | 登录成功 | -| 协议未开启 | 登录失败 | -| 已开启但尚未生成授权码 | 登录失败 | -| 授权码已撤销或重新生成 | 旧授权码登录失败,新授权码登录成功 | -| 使用网页登录密码 | 登录失败 | -| 使用短账号名(例如 `alice`) | 登录失败 | -| 使用未验证或未绑定邮箱地址 | 登录失败 | -| SMTP 587 在 STARTTLS 前认证 | 服务端拒绝认证 | -| POP3 未完成 TLS 或 STLS 就认证 | 服务端拒绝认证 | +## 开发者与集成文档 -### 当前自动化验证范围 +系统针对外部二次开发与集成提供详尽文档: -项目自动化测试已经覆盖统一协议认证服务、控制器接口、SMTP 会话认证、POP3 会话认证、IMAP 原始 `LOGIN`、完整邮箱地址、协议开关、授权码撤销、重新生成和网页登录密码拒绝。自动化测试不能替代生产环境中的 DNS、证书、防火墙、Nginx、真实邮件客户端和实际投递验收,因此部署后仍需按上面的命令执行一次真实验证。 +- 📘 **[后端接口说明文档](docs/后端接口说明文档.md)**:包含全量 HTTP API 接口、身份验证、CSRF 防护、邮件收发与系统在线无感迁移规范; +- 🔌 **[插件开发说明文档](docs/插件开发说明.md)**:包含独立子进程架构、标准 Stdio/JSON 通信协议、反垃圾过滤与即时通讯推送 Hook 开发教程; +- 🌐 **[Nginx反代与证书部署说明](docs/Nginx反代与证书部署说明.md)**:外部高防 CDN、Nginx 反向代理配置与证书托管指引。 -### PMail 原版无法登录的结论 +--- -PMail 原版不能作为当前 Smail 的第三方协议登录测试客户端。它的旧登录流程会截断包含 `@` 的登录名,没有 Smail 的协议开关和授权码模型,并且按网页登录密码校验;Smail 则要求“完整邮箱地址 + 对应协议授权码”。因此,把 Smail 的授权码填入 PMail 原版后登录失败属于兼容性限制,不应通过接受短账号名或网页登录密码来规避。 +## 开源协议与鸣谢 -## 自动化构建发布与 CI/CD 工作流 - -本项目在两个代码仓库中均维护了全自动化的构建与发布工作流: -- **GitHub**: [https://github.com/xuanspark/Smail.git](https://github.com/xuanspark/Smail.git) -- **PCUX Git**: [https://git.pcux.cn/xuans/Smail.git](https://git.pcux.cn/xuans/Smail.git) - -支持全自动化多平台构建与发布包生成(自包含完整的前端与静态内嵌资源): -- **Linux**: Smail_linux_amd64.tar.gz / Smail_linux_arm64.tar.gz -- **Windows**: Smail_windows_amd64.zip / Smail_windows_arm64.zip -- **macOS**: Smail_darwin_amd64.tar.gz / Smail_darwin_arm64.tar.gz - -部署包中内置了最新完整编译的前端资源与插件,解压即可运行。 +- 本项目基于开源项目 [PMail](https://github.com/JMisFilter/pmail) 进行二次修改与持续演进。 +- 遵循相应开源许可协议分发。 diff --git a/docs/后端接口说明文档.md b/docs/后端接口说明文档.md index 57ff32ca..7737196c 100644 --- a/docs/后端接口说明文档.md +++ b/docs/后端接口说明文档.md @@ -1,770 +1,300 @@ # Smail 后端接口说明文档 -> 本文档用于说明当前 Smail 后端 HTTP API 的实际调用方式,并对照原版 PMail《后端接口文档》核对接口是否仍然存在。 -> -> 核对基准:当前代码分支 `main`,提交 `6ec4628`,核对日期:2026-08-27。 +本文档面向所有使用 Smail 的开发者、运维人员及第三方系统集成者,全面公开 Smail 当前版本的 HTTP Web API 接口规范、身份鉴权机制、数据传输格式与各模块调用方式。 -## 1. 文档范围和结论 +--- -原版 PMail 文档包含 9 个基础接口。当前 Smail 仍然保留其中 8 个接口的功能入口,但有以下路径或调用方式变化: +## 1. 基础规范与公共约定 -| 编号 | 原版接口 | 当前实际接口 | 当前状态 | 主要差异 | -|---|---|---|---|---| -| 1 | `/api/ping` | `/api/ping` | 存在 | 当前返回统一 JSON,不再是纯文本 `pong` | -| 2 | `/api/login` | `/api/login` | 存在 | 只接受 `POST`;使用会话 Cookie 和 CSRF Cookie,不使用原版文档所述的 `token` 请求头 | -| 3 | `/api/group` | `/api/group` | 部分兼容 | 当前只接受 `GET`,原版写的 `POST` 不再可用;另有 `/api/group/list` | -| 4 | `/api/email/list` | `/api/email/list` | 存在 | 只接受 `POST`,分页参数增加范围限制 | -| 5 | `/api/detail` | `/api/email/detail` | 路径已变更 | 原路径不存在,必须使用 `/api/email/detail` | -| 6 | `/api/email/send` | `/api/email/send` | 存在 | 只接受 `POST`,增加发件人校验、附件和收件人数限制 | -| 7 | `/api/settings/modify_password` | `/api/settings/modify_password` | 存在 | 当前需要同时提交 `current_password` 和 `password` | -| 8 | `/attachments/` | `/attachments/{邮件ID}/{内容标识}` | 存在 | 当前只接受 `GET`,用于内联展示附件内容 | -| 9 | `/attachments/download/` | `/attachments/download/{邮件ID}/{附件序号}` | 存在 | 当前只接受 `GET`,最后一段是附件序号,不是附件数据库 ID | +### 1.1 接口地址与协议 +- **协议**:HTTP / HTTPS(生产环境推荐启用 HTTPS) +- **规范路径前缀**:所有规范接口统一以 `/api/v1/` 为前缀;系统同时向下兼容 `/api/` 别名。 +- **数据传输格式**:所有 POST / PUT / PATCH 请求正文(Body)必须为 `application/json`;响应格式统一为 `application/json; charset=utf-8`。 -当前路由注册以 `backend/listen/http_server/http_server.go` 为准,接口处理逻辑以 `backend/controllers` 和 `backend/controllers/email` 为准。 - -## 2. 通用调用约定 - -### 2.1 基础地址 - -以下示例使用: - -```text -https://mail.example.com -``` - -请替换为实际的 Smail Web 地址。开发环境通过前端 HTTPS 入口访问: - -```text -https://example.com -``` - -开发后端 API 独立监听 `http://127.0.0.1:5201`,由前端开发服务代理 `/api` 和 `/attachments` 请求。浏览器不应绕过前端入口直接访问后端端口。生产环境应始终使用正式 HTTPS 入口。 - -### 2.2 通用响应格式 - -除附件内容下载接口外,JSON 接口统一返回以下结构: +### 1.2 统一响应结构 +所有接口在 HTTP 状态码为 200 时,均返回以下统一 JSON 结构: ```json { - "errorNo": 0, - "errorMsg": "", + "code": 0, + "message": "success", "data": {} } ``` -字段说明: +- **code** (`int`): 业务状态码。`0` 表示操作成功;非 `0` 表示业务逻辑异常或失败。 +- **message** (`string`): 操作结果提示或错误说明(中文)。 +- **data** (`object` | `array` | `null`): 具体业务返回数据。 -| 字段 | 类型 | 说明 | -|---|---|---| -| `errorNo` | number | `0` 表示成功;非 `0` 表示失败。常见值:`100` 参数错误、`403` 未登录、`405` 无权限、`500` 服务端错误 | -| `errorMsg` | string | 错误说明。生产环境不应依赖错误文本判断业务分支,应优先判断 `errorNo` | -| `data` | any | 成功数据或错误附加数据 | +### 1.3 身份认证与安全机制 (Authentication & CSRF) +1. **会话认证 (Cookie)**: + - 用户登录成功后,服务端会在响应头中写入会话 Cookie:`smail_session`(带有 `HttpOnly` 与 `SameSite` 策略)。 + - 随后的所有受保护接口依赖该 Cookie 进行状态鉴权。 +2. **跨站请求伪造防护 (CSRF Token)**: + - 对于所有的状态变更请求(POST、PUT、DELETE),客户端必须在 HTTP 请求头中携带: + ```http + X-CSRF-Token: <从初始化或登录响应中获取的有效Token> + ``` +3. **角色与权限模型**: + - **普通用户 (Normal User)**:管理个人邮件、个人安全码、TOTP、客户端专属发信凭据、收信规则、联系人分组等。 + - **管理员 (Admin) / 超级管理员 (SuperAdmin)**:除普通权限外,还拥有系统级配置审计、用户账号生命周期管理、全站日志检索、域名解析与证书状态审查、数据库无感在线迁移等全局权限。 -请求方法不正确时,路由层返回 HTTP `405 Method Not Allowed`,并通过 `Allow` 响应头提示允许的方法;此时不一定返回上面的 JSON 结构。 +--- -### 2.3 登录态和 CSRF +## 2. 基础与探活接口 -除探活、登录和公开的密码恢复流程外,邮件、分组、密码修改等接口都需要登录态。 - -登录成功后,服务端会设置: - -1. 会话 Cookie,用于识别登录用户; -2. `smail_csrf` Cookie,用于保存 CSRF Token; -3. 后续状态修改请求需要在 `X-CSRF-Token` 请求头中提交与 `smail_csrf` Cookie 相同的值。 - -对于携带登录会话 Cookie 的状态修改请求,还需要使用同源的 `Origin`;跨站请求或 CSRF Token 不匹配时会被拒绝。 - -建议使用浏览器或 HTTP 客户端的 Cookie Jar 保存登录后的 Cookie,不要手工复制会话 Cookie 到代码或日志中。 - -### 2.4 请求头 - -JSON 请求通常应携带: - -```http -Content-Type: application/json -``` - -需要登录的状态修改请求示例: - -```http -Cookie: 会话Cookie; smail_csrf=CSRF_TOKEN -X-CSRF-Token: CSRF_TOKEN -Origin: https://mail.example.com -``` - -`Lang` 请求头可以指定返回语言,例如: - -```http -Lang: zh-CN -``` - -未指定时由服务端使用默认语言处理。 - -### 2.5 通用错误处理 - -调用方建议按以下顺序处理: - -1. 先检查 HTTP 状态码; -2. 对 JSON 响应解析 `errorNo`、`errorMsg` 和 `data`; -3. 收到 `403` 或业务错误码表示登录失效时,重新登录; -4. 收到 `405` 时检查请求方法,不要重试相同方法; -5. 不要把密码、会话 Cookie、CSRF Token、完整邮箱地址写入日志。 - -## 3. 原版基础接口对照和调用说明 - -## 3.1 服务探活 - -### 接口信息 - -| 项目 | 内容 | -|---|---| -| 原版路径 | `/api/ping` | -| 当前路径 | `/api/ping` | -| 当前方法 | `GET`、`POST` 均可到达处理器;建议使用 `GET` | -| 是否需要登录 | 否 | -| 请求体 | 无 | -| 返回类型 | JSON | - -### 调用示例 - -```bash -curl -X GET "https://mail.example.com/api/ping" -``` - -也可以使用: - -```bash -curl -X POST "https://mail.example.com/api/ping" -``` - -### 返回示例 - -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": "pong" -} -``` - -### 与原版差异 - -原版文档把返回格式写成 `text`,示例为纯文本 `pong`。当前代码通过统一响应封装返回 JSON,实际数据位于 `data` 字段中。 - -## 3.2 用户登录 - -### 接口信息 - -| 项目 | 内容 | -|---|---| -| 原版路径 | `/api/login` | -| 当前路径 | `/api/login` | -| 方法 | `POST` | -| 是否需要登录 | 否 | -| 请求格式 | `application/json` | -| 返回类型 | JSON | - -### 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|---|---|---:|---| -| `identifier` | string | 否 | 登录标识。当前优先使用该字段,可填写账号或完整邮箱 | -| `account` | string | 否 | 兼容原版字段。当 `identifier` 为空时使用该字段 | -| `password` | string | 是 | 登录密码 | - -`identifier` 和 `account` 至少提供一个。为了兼容原版客户端,可以继续提交 `account`;新客户端建议使用 `identifier`。 - -### 调用示例 - -兼容原版字段: - -```bash -curl -X POST "https://mail.example.com/api/login" \ - -H "Content-Type: application/json" \ - -c cookies.txt \ - -d '{ - "account": "admin", - "password": "your-password" - }' -``` - -使用新的登录标识字段: - -```bash -curl -X POST "https://mail.example.com/api/login" \ - -H "Content-Type: application/json" \ - -c cookies.txt \ - -d '{ - "identifier": "admin@example.com", - "password": "your-password" - }' -``` - -### 成功返回示例 - -普通登录直接完成时,返回: - -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": { - "account": "admin", - "name": "管理员", - "role": "super_admin", - "is_admin": 1, - "domains": [ - "example.com" - ] - } -} -``` - -登录成功时,服务端同时通过 `Set-Cookie` 设置会话 Cookie 和 CSRF Cookie。客户端必须保存这两个 Cookie,后续接口才能继续调用。 - -### 二次验证情况 - -如果当前账号启用了登录二次验证,密码正确后可能返回一个待完成的验证数据,而不是直接建立完整登录态。客户端应根据返回的 `data` 调用登录验证接口: - -```text -POST /api/security/login/verify -``` - -该流程不属于原版 PMail 基础接口,详细接口以本文第 4 节的当前安全接口表和前端调用为准。 - -### 失败返回示例 - -```json -{ - "errorNo": 100, - "errorMsg": "参数错误", - "data": "" -} -``` - -为了防止账号枚举,登录失败、账号不存在、密码错误和登录限流通常使用相同的业务错误响应,调用方不要根据错误文本判断账号是否存在。 - -### 与原版差异 - -原版文档提到可以通过请求头 `token` 进行验签。当前代码路由和认证逻辑未发现该兼容方式,当前登录态以服务端会话 Cookie 为准,不应使用 `token` 请求头替代登录。 - -## 3.3 获取邮件分组树 - -### 接口信息 - -| 项目 | 内容 | -|---|---| -| 原版路径 | `/api/group` | -| 当前路径 | `/api/group` | -| 方法 | `GET` | -| 原版方法 | `POST/GET` | -| 是否需要登录 | 是 | -| 请求体 | 无 | -| 返回类型 | JSON | - -当前 `/api/group` 只注册了 `GET`。使用原版文档中的 `POST` 调用会返回 HTTP `405`。 - -### 调用示例 - -```bash -curl -X GET "https://mail.example.com/api/group" \ - -b cookies.txt -``` - -如果是浏览器外的状态修改场景,读取接口不需要提交 CSRF Token;但必须携带有效会话 Cookie。 - -### 返回示例 - -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": [ - { - "label": "收件箱", - "tag": "{\"type\":0,\"status\":-1,\"group_id\":0}" - }, - { - "label": "发件箱", - "tag": "{\"type\":1,\"status\":-1}" - }, - { - "label": "草稿箱", - "tag": "{\"type\":0,\"status\":4}" +### 2.1 服务健康探活 +- **接口路径**:`GET /api/v1/ping`(兼容别名 `GET /api/ping`) +- **权限要求**:公开访问,无需认证 +- **响应示例**: + ```json + { + "code": 0, + "message": "pong", + "data": { + "status": "healthy", + "version": "V2.14.0" } - ] -} -``` - -### 当前相关分组接口 - -| 方法 | 路径 | 说明 | 请求体 | -|---|---|---|---| -| `GET` | `/api/group` | 获取前端使用的分组树 | 无 | -| `GET` | `/api/group/list` | 获取默认分组和用户自定义分组列表 | 无 | -| `POST` | `/api/group/add` | 创建自定义分组 | `{"name":"项目邮件","parent_id":0}` | -| `POST` | `/api/group/del` | 删除自定义分组 | `{"id":1}` | - -`POST /api/group/add` 和 `POST /api/group/del` 属于状态修改接口,需要登录态和 CSRF Token。 - -## 3.4 获取邮件列表 - -### 接口信息 - -| 项目 | 内容 | -|---|---| -| 路径 | `/api/email/list` | -| 方法 | `POST` | -| 是否需要登录 | 是 | -| 请求格式 | `application/json` | -| 返回类型 | JSON | - -### 请求参数 - -| 参数 | 类型 | 必填 | 默认值 | 说明 | -|---|---|---:|---:|---| -| `keyword` | string | 否 | 空字符串 | 邮件搜索关键词,最多 512 字节 | -| `tag` | string | 否 | 全部邮件 | JSON 字符串形式的筛选条件 | -| `current_page` | integer | 否 | `1` | 当前页,从 `1` 开始,最大 `10000` | -| `page_size` | integer | 否 | `15` | 每页数量,最大 `100` | - -`tag` 是一个字符串字段,内容需要再次编码为 JSON,例如: - -```json -"{\"type\":0,\"status\":-1,\"group_id\":0}" -``` - -### 调用示例 - -```bash -curl -X POST "https://mail.example.com/api/email/list" \ - -H "Content-Type: application/json" \ - -b cookies.txt \ - -H "X-CSRF-Token: CSRF_TOKEN" \ - -H "Origin: https://mail.example.com" \ - -d '{ - "keyword": "验证码", - "tag": "{\"type\":0,\"status\":-1,\"group_id\":0}", - "current_page": 1, - "page_size": 15 - }' -``` - -### 返回示例 - -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": { - "current_page": 1, - "total_page": 1, - "list": [ - { - "id": 1, - "title": "邮件标题", - "desc": "邮件正文摘要", - "datetime": "2026-08-27 08:44:00", - "is_read": false, - "sender": { - "Name": "发件人", - "EmailAddress": "sender@example.com" - }, - "to": [ - { - "Name": "收件人", - "EmailAddress": "admin@example.com" - } - ], - "dangerous": false, - "error": "" - } - ] } -} -``` + ``` -### 分页说明 +--- -- 不提交分页参数时使用 `current_page=1`、`page_size=15`; -- `current_page` 小于 `1` 或大于 `10000` 会被拒绝; -- `page_size` 小于 `1` 或大于 `100` 会被拒绝; -- `keyword` 超过 512 字节会被拒绝; -- `total_page` 在没有邮件时为 `0`。 +## 3. 身份验证与会话管理 (Auth) -## 3.5 获取邮件详情 - -### 接口信息 - -| 项目 | 内容 | -|---|---| -| 原版路径 | `/api/detail` | -| 当前路径 | `/api/email/detail` | -| 方法 | `POST` | -| 是否需要登录 | 是 | -| 请求格式 | `application/json` | -| 返回类型 | JSON | - -### 请求参数 - -| 参数 | 类型 | 必填 | 说明 | -|---|---|---:|---| -| `id` | integer | 是 | 邮件 ID,必须大于 `0` | - -### 调用示例 - -```bash -curl -X POST "https://mail.example.com/api/email/detail" \ - -H "Content-Type: application/json" \ - -b cookies.txt \ - -H "X-CSRF-Token: CSRF_TOKEN" \ - -H "Origin: https://mail.example.com" \ - -d '{ - "id": 1 - }' -``` - -### 返回示例 - -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": { - "id": 1, - "type": 0, - "subject": "邮件标题", - "reply_to": "", - "from_name": "发件人", - "from_address": "sender@example.com", - "to": "[{\"Name\":\"收件人\",\"EmailAddress\":\"admin@example.com\"}]", - "bcc": "[]", - "cc": "[]", - "sender": "{\"Name\":\"发件人\",\"EmailAddress\":\"sender@example.com\"}", - "spf_check": 1, - "dkim_check": 1, - "status": 1, - "send_time": "2026-08-27 08:44:00", - "send_date": "2026-08-27 08:44:00", - "update_time": "2026-08-27 08:44:00", - "create_time": "2026-08-27 08:44:00", - "text": "纯文本正文", - "html": "
HTML正文
", - "error": "", - "attachments": [ - { - "Filename": "report.pdf", - "ContentType": "application/pdf", - "Index": 0 - } - ] +### 3.1 用户账号登录 +- **接口路径**:`POST /api/v1/login`(兼容别名 `POST /api/login`) +- **权限要求**:公开访问 +- **请求参数**: + ```json + { + "username": "admin@example.com", + "password": "YourStrongPassword" } -} -``` + ``` +- **响应字段**: + ```json + { + "code": 0, + "message": "登录成功", + "data": { + "user_id": 1, + "username": "admin@example.com", + "is_admin": true, + "require_2fa": false, + "csrf_token": "3f81a7b..." + } + } + ``` + > 若账号启用了二次验证(TOTP / Passkey),则 `require_2fa` 为 `true`,此时登录流程尚未完成,需调用 3.2 接口进行校验。 -### 与原版差异 +### 3.2 登录二次安全验证 +- **接口路径**:`POST /api/v1/security/login/verify` +- **权限要求**:初次密码校验通过后的临时认证状态 +- **请求参数**: + ```json + { + "verify_type": "totp", + "code": "123456" + } + ``` +- **响应结果**:二次验证通过后,下发正式的会话凭据。 -原版文档使用 `/api/detail`。当前该路径没有注册,必须改为 `/api/email/detail`。邮件详情请求会标记邮件为已读,因此调用该接口不是纯读取操作;使用 `POST` 也符合当前路由约束。 +### 3.3 退出登录 (Logout) +- **接口路径**:`POST /api/v1/logout`(兼容别名 `POST /api/logout`) +- **权限要求**:已登录用户 +- **响应结果**:清除服务端会话并作废 Cookie。 -## 3.6 发送邮件 +--- -### 接口信息 +## 4. 账号多重安全与多因素凭据 (Security & 2FA) -| 项目 | 内容 | -|---|---| -| 路径 | `/api/email/send` | -| 方法 | `POST` | -| 是否需要登录 | 是 | -| 请求格式 | `application/json` | -| 返回类型 | JSON | -| 请求体上限 | 40 MiB | +### 4.1 TOTP 双因素认证管理 +- **获取 TOTP 绑定秘钥与二维码**:`GET /api/v1/security/totp/setup` + - 返回 TOTP 秘钥 `secret` 与用于扫码绑定的标准 `otpauth://` URI。 +- **验证并启用 TOTP**:`POST /api/v1/security/totp/enable` + - 请求参数:`{ "code": "6位动态验证码" }` +- **停用 TOTP**:`POST /api/v1/security/totp/disable` + - 请求参数:`{ "password": "当前用户密码" }` -### 请求参数 +### 4.2 Passkey / WebAuthn 硬件通行密钥 +- **获取注册挑战参数**:`GET /api/v1/security/webauthn/register/begin` +- **完成密钥注册**:`POST /api/v1/security/webauthn/register/finish` +- **删除已绑定的安全密钥**:`DELETE /api/v1/security/webauthn/keys/:key_id` -| 参数 | 类型 | 必填 | 说明 | -|---|---|---:|---| -| `reply_to` | array | 否 | 回复地址列表,每项包含 `name`、`email` | -| `from` | object | 否 | 发件人,包含 `name`、`email`;邮箱为空时使用当前账号地址 | -| `to` | array | 是 | 收件人列表,每项包含 `name`、`email` | -| `bcc` | array | 否 | 密送列表 | -| `cc` | array | 否 | 抄送列表 | -| `subject` | string | 是 | 邮件标题 | -| `text` | string | 否 | 纯文本正文 | -| `html` | string | 否 | HTML 正文 | -| `sender` | object | 否 | SMTP Envelope Sender;为空时使用 `from` | -| `read_receipt` | array | 否 | 已读回执地址列表 | -| `attrs` | array | 否 | 附件列表,每项包含 `name`、`data` | +### 4.3 安全恢复码 (Recovery Codes) +- **查看/生成新安全恢复码**:`POST /api/v1/security/recovery-codes/generate` +- **使用恢复码重置认证**:`POST /api/v1/security/recovery-codes/verify` -`attrs[].data` 必须是 Data URL 格式的 Base64 数据,例如: +### 4.4 外部安全备用邮箱绑定 +- **发送绑定验证码**:`POST /api/v1/security/external-email/send-code` + - 请求参数:`{ "external_email": "backup@gmail.com" }` +- **确认绑定外部安全邮箱**:`POST /api/v1/security/external-email/confirm` + - 请求参数:`{ "external_email": "backup@gmail.com", "code": "123456" }` -```text -data:application/pdf;base64,BASE64_DATA -``` +--- -### 调用示例 +## 5. 协议专属发信凭据与系统授权 (Credentials) -```bash -curl -X POST "https://mail.example.com/api/email/send" \ - -H "Content-Type: application/json" \ - -b cookies.txt \ - -H "X-CSRF-Token: CSRF_TOKEN" \ - -H "Origin: https://mail.example.com" \ - -d '{ - "from": { - "name": "管理员", - "email": "admin@example.com" - }, - "to": [ - { - "name": "收件人", - "email": "user@example.com" - } - ], +Smail 严格遵守权限最小化原则,杜绝直接暴露主账号密码用于第三方发信,提供细粒度的独立授权。 + +### 5.1 客户端专属发信授权码 (Client Credentials) +用于 Foxmail、Outlook、手机邮件客户端等 SMTP/IMAP/POP3 专属接入。 +- **获取当前用户凭据列表**:`GET /api/v1/credentials` +- **生成专属客户端授权码**:`POST /api/v1/credentials` + - 请求参数: + ```json + { + "client_name": "Mac Mail", + "service_type": "smtp" + } + ``` + - 响应结果返回一次性高强度授权密码(明文仅显示一次)。 +- **修改/启停专属授权**:`PUT /api/v1/credentials/:id/status` +- **删除专属授权**:`DELETE /api/v1/credentials/:id` + +### 5.2 系统通知与外部服务发信授权 (System Notification Credentials) +专为系统监控、告警、微服务等第三方系统发信设计。 +- **获取系统通知凭据列表**:`GET /api/v1/credentials/system-notifications` +- **创建自定义服务发信授权**:`POST /api/v1/credentials/system-notifications` + - 请求参数: + ```json + { + "service_name": "用户注册中心", + "sender_display_name": "系统自动通知", + "rate_limit_per_hour": 100 + } + ``` +- **查看与重置服务发信密钥**:`POST /api/v1/credentials/system-notifications/:id/reveal` + +--- + +## 6. 邮件收发与管理 (Email Operations) + +### 6.1 邮件列表查询 +- **接口路径**:`GET /api/v1/email/list`(兼容别名 `GET /api/email/list`) +- **查询参数**: + - `box_type` (`string`): 邮箱分类:`inbox`(收件箱)、`sent`(已发送)、`draft`(草稿箱)、`trash`(垃圾箱/已删除)。 + - `page` (`int`): 当前页码,从 1 开始。 + - `page_size` (`int`): 每页条数,默认 20。 + - `keyword` (`string`): 搜索关键字(匹配发件人、收件人、主题)。 + +### 6.2 邮件详情查看 +- **接口路径**:`GET /api/v1/email/detail`(兼容别名 `GET /api/email/detail`) +- **查询参数**:`id` (`int`) 邮件主键 ID。 +- **响应数据**:包含邮件正文 HTML/纯文本、完整的发件人显示名、原始时间戳、DKIM/SPF 校验结果状态以及附件元数据列表。 + +### 6.3 邮件发送 +- **接口路径**:`POST /api/v1/email/send`(兼容别名 `POST /api/email/send`) +- **请求参数**: + ```json + { + "to": ["recipient@domain.com"], "cc": [], "bcc": [], - "subject": "测试邮件", - "text": "这是纯文本正文。", - "html": "

这是 HTML 正文。

", - "attrs": [] - }' -``` + "subject": "邮件主题", + "content_html": "

邮件正文内容

", + "content_text": "邮件正文纯文本", + "attachments": ["temp_file_token_1"], + "sender_name": "自定义发信人名称" + } + ``` -### 成功返回 +### 6.4 邮件草稿保存与更新 +- **接口路径**:`POST /api/v1/email/draft` +- **接口路径(更新)**:`PUT /api/v1/email/draft/:id` -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": "操作成功" -} -``` +### 6.5 邮件删除与批量清理 +- **接口路径**:`POST /api/v1/email/delete`(兼容别名 `POST /api/email/delete`) +- **请求参数**: + ```json + { + "ids": [101, 102], + "permanent": false + } + ``` + > `permanent: false` 移入废纸篓;`permanent: true` 物理彻底粉碎删除。 -接口返回成功表示邮件已经通过参数校验并创建发送任务。实际投递结果可能在异步处理后才确定,失败信息会写入邮件状态,调用方应通过邮件列表或详情接口检查最终状态。 +### 6.6 附件上传与安全下载 +- **上传附件**:`POST /api/v1/attachments/upload`(使用 `multipart/form-data` 上传) +- **下载附件**:`GET /api/v1/attachments/download/:attachment_id` -### 当前限制 +--- -- `to` 至少包含一个收件人; -- `to`、`cc`、`bcc`、`reply_to` 合计最多 `100` 个地址; -- 附件最多 `20` 个; -- 单个附件最大 `10 MiB`; -- 附件总大小最大 `25 MiB`; -- 邮件正文最大约 `8 MiB`; -- `subject` 必填; -- 普通用户不能伪造未授权的内部发件人地址; -- 附件文件名会进行路径和控制字符清理。 +## 7. 智能规则引擎与过滤器 (Rule Engine) -## 3.7 修改当前账号密码 +### 7.1 收信过滤规则列表 +- **接口路径**:`GET /api/v1/rules` +- **响应数据**:包含规则优先级、触发条件(发件人包含、主题正则、域名匹配等)与执行动作(直接标记垃圾、自动归档指定分组、自动转发出站等)。 -### 接口信息 +### 7.2 新建/编辑收信规则 +- **接口路径**:`POST /api/v1/rules` / `PUT /api/v1/rules/:id` -| 项目 | 内容 | -|---|---| -| 原版路径 | `/api/settings/modify_password` | -| 当前路径 | `/api/settings/modify_password` | -| 方法 | `POST` | -| 是否需要登录 | 是 | -| 请求格式 | `application/json` | -| 返回类型 | JSON | +### 7.3 发件人黑白名单管理 +- **接口路径**:`GET /api/v1/email/sender-filters` +- **添加黑白名单**:`POST /api/v1/email/sender-filters` + - 请求参数:`{ "email_or_domain": "spammer.com", "filter_type": "blacklist" }` -### 请求参数 +--- -| 参数 | 类型 | 必填 | 说明 | -|---|---|---:|---| -| `current_password` | string | 是 | 当前密码 | -| `password` | string | 是 | 新密码,长度为 8 到 12 字节 | +## 8. 联系人与邮件分组 (Groups & Contacts) -### 调用示例 +- **获取邮件分组列表**:`GET /api/v1/groups` +- **新增邮件分组**:`POST /api/v1/groups` +- **修改分组名称**:`PUT /api/v1/groups/:id` +- **删除分组**:`DELETE /api/v1/groups/:id` -```bash -curl -X POST "https://mail.example.com/api/settings/modify_password" \ - -H "Content-Type: application/json" \ - -b cookies.txt \ - -H "X-CSRF-Token: CSRF_TOKEN" \ - -H "Origin: https://mail.example.com" \ - -d '{ - "current_password": "old-password", - "password": "new-password" - }' -``` +--- -### 成功返回 +## 9. 用户账号生命周期管理 (User Management) -```json -{ - "errorNo": 0, - "errorMsg": "", - "data": "操作成功" -} -``` +> **注**:本模块接口仅限拥有管理员(Admin)或超级管理员权限的用户访问。 -修改成功后,当前账号的安全凭据和登录会话会按服务端策略刷新或撤销。调用方如果收到会话失效,应重新登录并重新获取 CSRF Token。 +### 9.1 用户账号列表 +- **接口路径**:`GET /api/v1/admin/users` +- **查询参数**:`page`, `page_size`, `search` -### 与原版差异 +### 9.2 创建全新账号 +- **接口路径**:`POST /api/v1/admin/users` +- **请求参数**: + ```json + { + "username": "newuser", + "domain": "example.com", + "password": "UserInitialPassword", + "quota_mb": 1024, + "is_admin": false + } + ``` -原版示例中的 `passowrd` 是拼写错误,当前代码使用正确字段 `password`。当前接口还要求提供 `current_password`,不能只提交新密码。 +### 9.3 编辑与修改账号 +- **接口路径**:`PUT /api/v1/admin/users/:user_id` +- **可更新属性**:用户限额、启用/禁用状态、管理员权限、个人显示名等。 -## 3.8 内联获取附件内容 +### 9.4 删除账号 +- **接口路径**:`DELETE /api/v1/admin/users/:user_id` +- **说明**:支持选择级联清理用户邮件数据或归档封存。 -### 接口信息 +--- -| 项目 | 内容 | -|---|---| -| 原版路径 | `/attachments/` | -| 当前路径 | `/attachments/{邮件ID}/{内容标识}` | -| 方法 | `GET` | -| 原版方法 | 文档写成 `POST`,但请求示例使用 `GET` | -| 是否需要登录 | 是 | -| 返回类型 | 附件原始内容 | +## 10. 系统运维、审计与数据库管理 (System & Migration) -其中: +### 10.1 系统日志查询 +- **接口路径**:`GET /api/v1/admin/logs` +- **参数支持**:`log_type`(邮件收发日志、系统审计日志、登录安全日志)、`level`(info/warn/error)、时间范围筛选。 -- `{邮件ID}` 是邮件 ID; -- `{内容标识}` 是邮件详情中附件的内容标识,通常对应内联资源的 Content-ID; -- 当前处理器会按路径读取这两个值,并检查当前用户是否有权访问该邮件附件。 +### 10.2 域名 DNS 与 SSL 证书状态检查 +- **接口路径**:`GET /api/v1/admin/domain/status` +- **检测项目**:MX 记录、A/AAAA 记录、SPF 记录、DKIM 公钥匹配、DMARC 策略有效性、SSL 证书有效天数。 -### 调用示例 - -```bash -curl -X GET "https://mail.example.com/attachments/1/image001.png" \ - -b cookies.txt \ - -o image001.png -``` - -### 返回说明 - -成功时返回附件原始字节,并设置对应的 `Content-Type`,例如: - -```http -Content-Type: image/png -``` - -失败时返回统一 JSON 错误响应。常见原因包括路径格式错误、附件不存在、附件不可用或当前用户无权访问。 - -## 3.9 下载附件 - -### 接口信息 - -| 项目 | 内容 | -|---|---| -| 原版路径 | `/attachments/download/` | -| 当前路径 | `/attachments/download/{邮件ID}/{附件序号}` | -| 方法 | `GET` | -| 是否需要登录 | 是 | -| 返回类型 | 文件流 | - -其中 `{附件序号}` 是邮件详情 `attachments` 数组中的 `Index`,当前从 `0` 开始,不是附件数据库 ID。 - -### 调用示例 - -```bash -curl -X GET "https://mail.example.com/attachments/download/1/0" \ - -b cookies.txt \ - -o report.pdf -``` - -### 返回响应头 - -成功时服务端返回: - -```http -Content-Type: application/octet-stream -X-Content-Type-Options: nosniff -Content-Disposition: attachment; filename="attachment"; filename*=UTF-8''report.pdf -``` - -服务端会清理文件名中的路径分隔符、换行符和控制字符,避免下载文件名被用于路径穿越或响应头注入。 - -## 4. 当前新增安全和账户接口 - -这些接口不在原版 PMail 的 9 个基础接口中,但已经注册在当前 Smail 路由中。它们属于当前前端登录、安全设置和密码恢复流程的一部分。 - -### 4.1 登录和恢复流程 - -| 方法 | 路径 | 是否公开 | 说明 | -|---|---|---:|---| -| `POST` | `/api/security/verification/request` | 否 | 请求验证信息 | -| `POST` | `/api/security/verification/verify` | 否 | 校验验证信息 | -| `POST` | `/api/security/login/verify` | 是 | 完成登录二次验证 | -| `POST` | `/api/security/recovery/begin` | 是 | 开始密码恢复流程 | -| `POST` | `/api/security/recovery/verify` | 是 | 校验密码恢复凭据 | -| `POST` | `/api/security/recovery/complete` | 是 | 完成密码恢复 | -| `POST` | `/api/security/recovery/webauthn/begin` | 是 | 开始 WebAuthn 恢复验证 | -| `POST` | `/api/security/recovery/webauthn/verify` | 是 | 完成 WebAuthn 恢复验证 | -| `POST` | `/api/logout` | 否 | 退出当前会话 | - -### 4.2 WebAuthn 和恢复码 - -| 方法 | 路径 | 说明 | -|---|---|---| -| `POST` | `/api/security/webauthn/registration/begin` | 开始注册安全密钥 | -| `POST` | `/api/security/webauthn/registration/finish` | 完成注册安全密钥 | -| `GET` | `/api/security/webauthn/credentials` | 查询当前账号安全密钥 | -| `POST` | `/api/security/webauthn/credentials/rename` | 重命名安全密钥 | -| `POST` | `/api/security/webauthn/credentials/revoke` | 撤销安全密钥 | -| `POST` | `/api/security/webauthn/login/begin` | 开始登录安全密钥验证 | -| `POST` | `/api/security/webauthn/login/finish` | 完成登录安全密钥验证 | -| `GET` | `/api/security/credentials/recovery-codes` | 查询恢复码状态,不返回历史恢复码原文 | -| `POST` | `/api/security/credentials/recovery-codes/generate` | 生成新的恢复码 | -| `POST` | `/api/security/credentials/recovery-codes/revoke` | 撤销恢复码 | -| 未限制 | `/api/security/credentials/question` | 密保问题相关流程入口,实际方法由处理器判断 | - -### 4.3 外部安全邮箱 - -| 方法 | 路径 | 说明 | -|---|---|---| -| `GET` | `/api/security/external-email/list` | 获取当前账号外部安全邮箱状态 | -| `POST` | `/api/security/external-email/bind` | 绑定外部安全邮箱 | -| `POST` | `/api/security/external-email/verify` | 验证外部安全邮箱 | -| `POST` | `/api/security/external-email/disable` | 禁用外部安全邮箱 | - -以上安全接口的请求参数和恢复状态机依赖当前安全设计,不应按照原版 PMail 的 `token` 模式调用。 - -## 5. 当前邮件和账户管理接口补充 - -| 方法 | 路径 | 说明 | -|---|---|---| -| `POST` | `/api/email/del` | 删除邮件 | -| `POST` | `/api/email/read` | 标记邮件已读 | -| `POST` | `/api/email/move` | 移动邮件到分组 | -| `POST` | `/api/rule/get` | 获取邮件规则 | -| `POST` | `/api/rule/add` | 新增邮件规则 | -| `POST` | `/api/rule/update` | 更新邮件规则 | -| `POST` | `/api/rule/del` | 删除邮件规则 | -| `POST` | `/api/user/create` | 创建用户,权限由当前角色控制 | -| `POST` | `/api/user/edit` | 编辑用户 | -| `POST` | `/api/user/info` | 获取用户信息 | -| `POST` | `/api/user/list` | 获取用户列表 | -| `GET` | `/api/plugin/list` | 获取插件列表 | -| `GET`、`POST` | `/api/plugin/settings/{插件名}/{操作}` | 读取或保存插件设置 | - -配置管理接口使用 `/api/v1/config/` 和 `/api/v1/audits/config` 路径,属于新的配置系统,不属于原版 PMail 基础接口;调用时需要按当前配置授权、审计和 CSRF 规则处理。 - -## 6. 原版接口迁移清单 - -使用原版 PMail 客户端迁移到当前 Smail 时,至少需要修改以下内容: - -| 原版调用 | 当前调用 | -|---|---| -| `POST /api/detail` | `POST /api/email/detail` | -| `POST /api/group` | `GET /api/group` | -| `POST /attachments/{邮件ID}/{附件标识}` | `GET /attachments/{邮件ID}/{附件标识}` | -| 仅提交 `password` 修改密码 | 同时提交 `current_password` 和 `password` | -| 使用 `token` 请求头认证 | 保存登录会话 Cookie,并在状态修改请求中提交 `X-CSRF-Token` | -| 将 `/api/ping` 当作纯文本读取 | 解析 JSON,并读取 `data` 中的 `pong` | - -## 7. 代码核对位置 - -本次对照使用以下当前代码位置作为实现依据: - -- 路由注册:`backend/listen/http_server/http_server.go` -- 请求上下文、登录态和 CSRF 校验:`backend/listen/http_server/https_server.go` -- 登录:`backend/controllers/login.go` -- 分组:`backend/controllers/group.go` -- 密码修改:`backend/controllers/settings.go` -- 附件:`backend/controllers/attachments.go` -- 邮件列表:`backend/controllers/email/list.go` -- 邮件详情:`backend/controllers/email/detail.go` -- 邮件发送:`backend/controllers/email/send.go` -- 统一 JSON 响应:`backend/dto/response/response.go` - -原版对照来源为 PMail Wiki 的《后端接口文档》。原版文档仅作为历史兼容性参考,接口是否可调用以当前 Smail 路由和处理器实现为准。 +### 10.3 跨数据库无感在线迁移 (Database Migration) +Smail 独创的三合一单数据库热切换与迁移接口: +- **发起数据库全量迁移**:`POST /api/v1/database/migrations` + - 请求参数: + ```json + { + "target_engine": "mysql", + "target_dsn": "user:pass@tcp(127.0.0.1:3306)/smail_db?charset=utf8mb4&parseTime=True&loc=Local" + } + ``` +- **查看迁移实时进度与回执**:`GET /api/v1/database/migrations/status` diff --git a/docs/插件开发说明.md b/docs/插件开发说明.md new file mode 100644 index 00000000..02c7e9fe --- /dev/null +++ b/docs/插件开发说明.md @@ -0,0 +1,162 @@ +# Smail 插件开发说明文档 + +Smail 提供灵活、高隔离、安全的插件扩展架构。无论是编写垃圾邮件智能拦截器,还是对接第三方即时通讯平台(如企业微信、钉钉、Telegram、飞书)进行实时邮件推送,开发者均可通过插件体系无缝扩展系统能力。 + +--- + +## 1. 插件架构设计 + +### 1.1 独立子进程运行模式 +- Smail 插件采用**独立操作系统子进程(Subprocess)**模式运行,而非脆弱的动态库链接(CGO 或 Go Plugin)。 +- **优势**: + - **故障彻底隔离**:任何插件发生内存泄漏或崩溃,绝不波及 Smail 主邮件服务的稳定运行。 + - **跨语言支持**:支持使用 Go、Python、Node.js、Rust 等任意可执行程序开发。 + - **嵌入式内置打包**:Smail 在编译发布时,通过 `hooks/bundle.go` 将官方核心插件直接内嵌于主二进制中,首次部署时自动解压释放。 + +### 1.2 标准 IPC 通信协议 +- **数据通道**:主程序通过标准输入(`Stdin`)向插件管道发送任务指令,插件通过标准输出(`Stdout`)回传处理结果。 +- **序列化格式**:每一帧交互均为换行符分隔的 **标准 JSON 字符串(JSON Lines)**。 + +--- + +## 2. 核心 Hook 钩子体系 + +Smail 在邮件流转的各关键生命周期定义了标准 Hook 点: + +| 钩子名称 (Hook Type) | 触发时机 | 插件职责与能力 | 典型应用 | +| :--- | :--- | :--- | :--- | +| `email_receive_filter` | SMTP 接收邮件并解析后、落库存储前 | 可审查邮件头、发件人信誉、正文内容、附件哈希;可**拦截(Reject)**或**放行(Pass)** | 垃圾邮件过滤、内容违规检测 (`spam_block`) | +| `email_received_notify` | 邮件成功入库且分发至收件箱后 | 异步获取入库邮件详情与收件人信息,触发外部投递 | 微信公众号/企业微信推送 (`wechat_push`)、Telegram 机器人通知 (`telegram_push`) | +| `email_send_filter` | 用户提交发信请求、投递出站前 | 审查外发敏感信息、数据防泄密 (DLP)、外发配额监控 | 合规审计、敏感词拦截 | + +--- + +## 3. 通信数据结构定义 + +### 3.1 邮件过滤 Hook (`email_receive_filter`) +#### 主程序输入至插件 (Stdin): +```json +{ + "hook": "email_receive_filter", + "data": { + "message_id": "", + "from": "spammer@bad.com", + "to": ["user@yourdomain.com"], + "subject": "免费领取大奖", + "content_text": "点击链接领取...", + "content_html": "

点击链接领取...

", + "client_ip": "1.2.3.4", + "spf_result": "pass", + "dkim_result": "none" + } +} +``` + +#### 插件响应回主程序 (Stdout): +```json +{ + "action": "reject", + "reason": "命中高危垃圾邮件关键词规则", + "mark_spam": true +} +``` +> 若允许放行,返回 `{ "action": "pass" }` 即可。 + +### 3.2 邮件通知 Hook (`email_received_notify`) +#### 主程序输入至插件 (Stdin): +```json +{ + "hook": "email_received_notify", + "data": { + "recipient": "admin@yourdomain.com", + "sender": "partner@client.com", + "subject": "关于项目合作推进的沟通", + "received_at": "2026-10-19T10:00:00+08:00", + "summary": "您好,附件为最新合同草案..." + } +} +``` + +#### 插件响应回主程序 (Stdout): +```json +{ + "status": "success", + "message": "已成功推送至目标渠道" +} +``` + +--- + +## 4. 最小插件开发示例 (Go 语言) + +以下为使用 Go 语言实现的极简邮件通知插件核心源码: + +```go +package main + +import ( + "bufio" + "encoding/json" + "fmt" + "os" +) + +type HookPayload struct { + Hook string `json:"hook"` + Data map[string]interface{} `json:"data"` +} + +type HookResponse struct { + Status string `json:"status"` + Message string `json:"message,omitempty"` +} + +func main() { + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + line := scanner.Bytes() + if len(line) == 0 { + continue + } + + var payload HookPayload + if err := json.Unmarshal(line, &payload); err != nil { + continue + } + + // 根据钩子类型处理业务 + switch payload.Hook { + case "email_received_notify": + subject, _ := payload.Data["subject"].(string) + recipient, _ := payload.Data["recipient"].(string) + + // 执行通知业务(例如调用 HTTP Webhook) + // sendWebhook(recipient, subject) + _ = recipient + _ = subject + + resp, _ := json.Marshal(HookResponse{ + Status: "success", + Message: "通知已推送", + }) + fmt.Println(string(resp)) + + default: + resp, _ := json.Marshal(HookResponse{Status: "pass"}) + fmt.Println(string(resp)) + } + } +} +``` + +--- + +## 5. 插件专属 UI 扩展与打包规范 + +如果插件需要在 Smail 设置中心展示可视化的配置表单(如 Telegram Bot Token 设置界面): +1. **单文件内嵌 UI**:前端开发采用 Vite + SingleFile 插件(如 `plugins/telegram-ui/`),将 HTML、CSS、JS 完全内联编译为一个单独的 `index.html`。 +2. **插件构建脚本**:使用项目自带的构建脚本执行批量编译: + ```bash + node deploy/build-plugins.mjs + ``` +3. **输出目录**:编译生成的跨架构插件可执行文件将统一放置在 `out/plugins//`,并在打包时自动集成进发布包的 `plugins/` 目录中。