Smail/README_CN.md
smail f60d3b0880
Some checks are pending
Security Checks / security (push) Waiting to run
整理前后端与测试构建目录并完善配置和安全引导
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
2026-09-05 19:19:52 +08:00

283 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Smail
> 一台服务器、一个域名、一行代码、一分钟时间,你就能够搭建出一个自己的域名邮箱。
Smail是一个追求极简部署流程、极致资源占用的个人域名邮箱服务器。单文件运行,包含完整的收发邮件服务和Web端邮件管理功能。只需一台服务器、一个域名、一行代码、一分钟部署时间,你就能够搭建出一个自己的域名邮箱。
欢迎各类PR,无论你是修复bug、新增功能、修改翻译。另外,也为这个项目征集一个漂亮可爱的Logo!
<img src="./docs/cn.gif" alt="Editor" width="800px">
## 为什么写这个项目
迫于越来越多的邮件服务商暂停了针对个人的域名邮箱服务(比如QQ邮箱、微软Outlook邮箱),因此考虑自建域名邮箱服务。
但是自建域名邮箱可选的程序并不多,且目标都不是针对个人使用场景设计的。个人服务器一般内存、CPU、硬盘配置都不高,针对公司场景使用的邮箱程序过于臃肿,
白白浪费资源。就拿我自己的服务器来说,我服务器配置为1核512M 10G硬盘,市面上绝大多数邮箱服务器安装上就把磁盘占满了,根本没法正常使用
## 项目优势
### 1、部署简单
使用Go语言编写,支持跨平台,编译后单文件运行,单文件包含完整的前后端代码。修改配置文件,运行即可。
### 2、资源占用极小
编译后二进制文件仅15MB,运行过程中占用内存10M以内。
### 3、安全方面
支持dkim、spf校验。正确配置的情况下,Email Test得分10分。
### 4、自动SSL证书
实现了ACME协议,程序将自动获取并更新Let’s Encrypt证书。
默认情况下,会为web后台也生成ssl证书,让后台使用https访问,如果你有自己的网关层,不需要https的话,在配置文件中将 `httpsEnabled`
设置为 `2`,这样管理后台就不会使用https协议。( 注意:即使你不需要https,也请保证ssl证书文件路径正确,http协议虽然不使用证书了,但是smtp协议还需要证书)
### 5、邮件客户端支持
只要支持pop3、smtp、imap协议的邮件客户端均可使用
### 6、多域名、多用户支持
支持多域名、多用户且完整支持收发邮件
# 如何部署
## 0、检查IP、域名
先去[spamhaus](https://check.spamhaus.org/)检查你的域名和服务器IP是否有屏蔽记录
## 1、下载文件
* [点击这里](https://git.pcux.cn/xuans/Smail/releases)下载一个与你匹配的程序文件。
* 或者使用Docker运行 `docker pull ghcr.io/jinnrry/pmail:latest`
## 2、运行
`./smail -p 80`
> `-p 指定引导设置界面的http端口,默认为80端口,注意该参数仅影响引导设置阶段,设置完成后如果需要修改端口请修改配置文件`
> [!IMPORTANT]
> 如果引导设置阶段使用非80端口,将无法自动设置SSL证书
或者
`docker run -p 25:25 -p 80:80 -p 443:443 -p 110:110 -p 465:465 -p 587:587 -p 995:995 -p 993:993 -v $(pwd)/config:/work/config ghcr.io/jinnrry/pmail:latest`
> [!IMPORTANT]
> 如果你服务器开启了防火墙,你需要打开25、80、110、443、465、587、995、993端口
## 3、配置
浏览器打开 `http://127.0.0.1` 或者是用你服务器公网IP访问,然后按提示配置
## 4、邮箱得分测试
建议找一下邮箱测试服务(比如[https://www.mail-tester.com/](https://www.mail-tester.com/))进行邮件得分检测,避免自己某些步骤漏配,导致发件进对方垃圾箱。
# 配置文件说明
```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` 启动开发服务。
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、认证和投递流程。
```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'
# 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'
```
认证成功后,服务端应接受认证并继续处理 `MAIL FROM`、`RCPT TO` 和邮件正文;如果 587 端口在 STARTTLS 前返回认证成功,说明服务端配置不符合安全要求。
### IMAP 验证
使用支持 IMAPS 的 `curl` 验证 993 端口:
```bash
curl --fail --silent --show-error \
--url 'imaps://imap.example.com/INBOX' \
--user 'alice@example.com:IMAP授权码'
```
能够建立 TLS 连接并返回收件箱信息,说明 IMAP 登录成功。将用户名改为 `alice`、密码改为网页登录密码,或先关闭 IMAP 开关后重新执行,均应认证失败。
### POP3 验证
使用支持 POP3S 的 `curl` 验证 995 端口:
```bash
curl --fail --silent --show-error \
--url 'pop3s://pop.example.com/' \
--user 'alice@example.com:POP3授权码' \
--list-only
```
能够建立 TLS 连接并返回邮件列表,说明 POP3 登录成功。普通 POP3 端口必须先完成 STLS,不能在明文连接阶段直接提交密码。
### 验证结果判定
| 测试项 | 预期结果 |
| --- | --- |
| 已开启协议 + 对应授权码 + 完整邮箱地址 | 登录成功 |
| 协议未开启 | 登录失败 |
| 已开启但尚未生成授权码 | 登录失败 |
| 授权码已撤销或重新生成 | 旧授权码登录失败,新授权码登录成功 |
| 使用网页登录密码 | 登录失败 |
| 使用短账号名(例如 `alice`) | 登录失败 |
| 使用未验证或未绑定邮箱地址 | 登录失败 |
| SMTP 587 在 STARTTLS 前认证 | 服务端拒绝认证 |
| POP3 未完成 TLS 或 STLS 就认证 | 服务端拒绝认证 |
### 当前自动化验证范围
项目自动化测试已经覆盖统一协议认证服务、控制器接口、SMTP 会话认证、POP3 会话认证、IMAP 原始 `LOGIN`、完整邮箱地址、协议开关、授权码撤销、重新生成和网页登录密码拒绝。自动化测试不能替代生产环境中的 DNS、证书、防火墙、Nginx、真实邮件客户端和实际投递验收,因此部署后仍需按上面的命令执行一次真实验证。
### PMail 原版无法登录的结论
PMail 原版不能作为当前 Smail 的第三方协议登录测试客户端。它的旧登录流程会截断包含 `@` 的登录名,没有 Smail 的协议开关和授权码模型,并且按网页登录密码校验;Smail 则要求“完整邮箱地址 + 对应协议授权码”。因此,把 Smail 的授权码填入 PMail 原版后登录失败属于兼容性限制,不应通过接受短账号名或网页登录密码来规避。