fix(submission): 调整 SMTP 提交与发件授权逻辑。
- 启用 SMTP submission 时改为强制使用可读证书文件,并禁止使用容器自带测试证书。 - 收紧发件人校验,拒绝未授权的 From 地址,并支持别名多目标授权。 - 优化发送队列重入与重复消息处理,避免重复记录冲突。 - 让提交证书按需热加载,并稳定 MIME 头序列化顺序。 - 更新部署示例与文档,明确 submission 的证书配置要求。
This commit is contained in:
+4
-4
@@ -28,7 +28,7 @@ LANQIN_PUBLIC_BASE_URL=https://mail.example.com
|
||||
|
||||
# 邮件客户端 TLS 证书。用于 SMTP 465/587、IMAP 993、POP3 995。
|
||||
# 生产环境请挂载真实证书,并确保域名包含 LANQIN_PUBLIC_HOSTNAME。
|
||||
# 留空时会使用容器自带 localhost 自签证书,第三方客户端会提示证书不匹配。
|
||||
# 留空时 Dovecot/Postfix 会使用容器自带 localhost 自签证书;LanQin API 的 SMTP submission 不会启用。
|
||||
LANQIN_TLS_CERT_FILE=
|
||||
LANQIN_TLS_KEY_FILE=
|
||||
|
||||
@@ -97,9 +97,9 @@ LANQIN_SMTP_PASSWORD=
|
||||
# 外部 SMTP 要求 STARTTLS / TLS 时改 true;本机 Postfix 默认 false。
|
||||
LANQIN_SMTP_REQUIRE_TLS=false
|
||||
|
||||
# 第三方客户端 SMTP 提交,由 LanQin API 监听 587/465。
|
||||
LANQIN_SUBMISSION_ADDR=:587
|
||||
LANQIN_SUBMISSION_TLS_ADDR=:465
|
||||
# 第三方客户端 SMTP 提交,由 LanQin API 监听 587/465;启用前必须配置可读 TLS 证书。
|
||||
LANQIN_SUBMISSION_ADDR=
|
||||
LANQIN_SUBMISSION_TLS_ADDR=
|
||||
LANQIN_SUBMISSION_MAX_MESSAGE_MB=35
|
||||
|
||||
# =========================
|
||||
|
||||
+3
-1
@@ -134,13 +134,15 @@ docker compose -f docker-compose.stack.yml -f docker-compose.stack.build.yml up
|
||||
## 邮件客户端 TLS 证书
|
||||
|
||||
Web 站点可以由宿主机 Nginx / 宝塔反代到容器 `80`,但 SMTP/IMAP/POP3 端口不会使用 Web 反代的证书。
|
||||
如果第三方客户端连接 `465/587/993/995` 时提示证书是 `localhost`,说明 LanQin API 或 Dovecot 仍在使用容器自带的测试证书。
|
||||
如果第三方客户端连接 `993/995` 时提示证书是 `localhost`,说明 Dovecot 仍在使用容器自带的测试证书。LanQin API 的 SMTP `465/587` submission 不会使用自签测试证书;启用前必须配置可读的真实证书。
|
||||
|
||||
生产环境请把域名证书挂载进容器,并在 `.env` 指向证书文件:
|
||||
|
||||
```env
|
||||
LANQIN_TLS_CERT_FILE=/certs/fullchain.pem
|
||||
LANQIN_TLS_KEY_FILE=/certs/privkey.pem
|
||||
LANQIN_SUBMISSION_ADDR=:587
|
||||
LANQIN_SUBMISSION_TLS_ADDR=:465
|
||||
```
|
||||
|
||||
单容器示例:
|
||||
|
||||
@@ -7,8 +7,8 @@ set -eu
|
||||
: "${LANQIN_ADDR:=127.0.0.1:8080}"
|
||||
: "${LANQIN_SMTP_HOST:=127.0.0.1}"
|
||||
: "${LANQIN_SMTP_PORT:=25}"
|
||||
: "${LANQIN_SUBMISSION_ADDR:=:587}"
|
||||
: "${LANQIN_SUBMISSION_TLS_ADDR:=:465}"
|
||||
: "${LANQIN_SUBMISSION_ADDR:=}"
|
||||
: "${LANQIN_SUBMISSION_TLS_ADDR:=}"
|
||||
: "${LANQIN_SUBMISSION_MAX_MESSAGE_MB:=35}"
|
||||
: "${LANQIN_MAILDIR_ROOT:=/var/mail/vhosts}"
|
||||
: "${LANQIN_TLS_CERT_FILE:=}"
|
||||
@@ -40,10 +40,18 @@ if [ -n "$LANQIN_TLS_CERT_FILE" ] || [ -n "$LANQIN_TLS_KEY_FILE" ]; then
|
||||
if [ -f "$LANQIN_TLS_CERT_FILE" ] && [ -f "$LANQIN_TLS_KEY_FILE" ]; then
|
||||
TLS_CERT="$LANQIN_TLS_CERT_FILE"
|
||||
TLS_KEY="$LANQIN_TLS_KEY_FILE"
|
||||
: "${LANQIN_SUBMISSION_ADDR:=:587}"
|
||||
: "${LANQIN_SUBMISSION_TLS_ADDR:=:465}"
|
||||
else
|
||||
echo "warning: LANQIN_TLS_CERT_FILE/LANQIN_TLS_KEY_FILE not readable; using snakeoil localhost certificate" >&2
|
||||
fi
|
||||
fi
|
||||
if [ -n "$LANQIN_SUBMISSION_ADDR$LANQIN_SUBMISSION_TLS_ADDR" ] && { [ "$TLS_CERT" = "/etc/ssl/certs/ssl-cert-snakeoil.pem" ] || [ "$TLS_KEY" = "/etc/ssl/private/ssl-cert-snakeoil.key" ]; }; then
|
||||
echo "warning: SMTP submission disabled because LANQIN_TLS_CERT_FILE/LANQIN_TLS_KEY_FILE are not configured with readable certificate files" >&2
|
||||
LANQIN_SUBMISSION_ADDR=""
|
||||
LANQIN_SUBMISSION_TLS_ADDR=""
|
||||
fi
|
||||
export LANQIN_SUBMISSION_ADDR LANQIN_SUBMISSION_TLS_ADDR
|
||||
|
||||
postconf -e "myhostname = ${LANQIN_PUBLIC_HOSTNAME}"
|
||||
postconf -e "myorigin = ${LANQIN_PUBLIC_HOSTNAME}"
|
||||
|
||||
@@ -5,6 +5,8 @@ services:
|
||||
environment:
|
||||
LANQIN_SMTP_HOST: ${LANQIN_STACK_SMTP_HOST:-postfix}
|
||||
LANQIN_SMTP_PORT: ${LANQIN_STACK_SMTP_PORT:-25}
|
||||
LANQIN_SUBMISSION_ADDR: ${LANQIN_SUBMISSION_ADDR:-}
|
||||
LANQIN_SUBMISSION_TLS_ADDR: ${LANQIN_SUBMISSION_TLS_ADDR:-}
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./mail:/var/mail/vhosts:ro
|
||||
|
||||
Reference in New Issue
Block a user