☰
SkillHub SMTP 邮箱配置指南:为密码重置验证码邮件搭建完整发信链路
2026/10/13 2:39:23 网站建设 项目流程
  • 人工智能
  • AI Agent
  • AI 技能
  • 后端
  • 前端

【免费下载链接】skillhub

Self-hosted, open-source agent skill registry for enterprises. Publish & version skill packages, govern with RBAC and audit logs, deploy on-premise with Docker or Kubernetes.

项目地址:https://gitcode.com/gh_mirrors/sk/skillhub
点击查看免费下载

本篇技术指南围绕 SkillHub(企业级自托管 Agent 技能注册中心)的「密码重置验证码邮件」功能,系统讲解如何为后端配置 SMTP 发信服务,覆盖生产/预发布环境(compose.release.yml+.env.release)与本地联调环境(直接注入后端环境变量)两条路径。读完本文,你将掌握 SkillHub 密码重置相关全部环境变量的含义与取值范围、三种开箱即用的配置方案(通用 SMTP、MailHog、线上 465 SSL)、完整的验证流程,以及认证失败、证书异常等常见问题的排障方法。

本文依据仓库中的 docs/19-smtp-password-reset-email-setup.md 展开,并结合 server/skillhub-app/src/main/resources/application.yml、PasswordResetService.java 等源码给出实现级证据。

1. 前置认知:SMTP 与验证码邮件的定位

SMTP(Simple Mail Transfer Protocol)本质是邮件传输协议,而不是某一厂商的单一产品。为 SkillHub 配置邮件发送时,你可以选择:

  • 企业邮箱 / 云邮箱:如自建邮件网关、各类云邮件服务的 SMTP 地址(一般同时提供 465 SSL 或 587 STARTTLS 两种接入方式);
  • 本地测试 SMTP 服务:如 MailHog(本文仅作示例工具名称,不输出外部链接),用于开发环境快速验证邮件链路而不依赖真实邮箱。

1.1 当前密码重置页面的统一入口

  • 前端统一使用/reset-password页面,该页面同时包含"发送验证码"和"提交新密码"两步,不再单独使用/forgot-password。
  • 对应前端实现位于 web/src/pages/reset-password.tsx:页面先校验邮箱格式并调用"发送验证码"接口,收到codeSentMessage提示后,再提交email + code + 新密码 + 确认密码完成重置。

1.2 验证码邮件的后端链路(源码视角)

从 PasswordResetService.java 可以看到完整实现:

  • 验证码生成:VERIFICATION_CODE_DIGITS = 6,使用SecureRandom生成 6 位数字验证码(源码第 217-221 行);
  • 验证码存储:不落明文,验证码经passwordEncoder.encode(code)哈希后随过期时间存入PasswordResetRequest,核对时用passwordEncoder.matches(code, request.getCodeHash())校验(源码第 140-146 行);
  • 邮件发送:通过 SpringJavaMailSender发送SimpleMailMessage,主题为SkillHub password reset verification code,正文包含验证码与有效分钟数(源码第 223-254 行);
  • 防账号枚举:自助请求对"不满足重置条件"的邮箱静默返回(不创建请求、不发邮件),接口永远返回通用成功提示(源码第 70-97 行)。

2. 需要配置的环境变量

以下变量均已被后端读取,是配置 SMTP 的全部入口:

变量名说明示例
SPRING_MAIL_HOSTSMTP 服务器地址smtp.example.com
SPRING_MAIL_PORTSMTP 端口465
SPRING_MAIL_USERNAMESMTP 用户名noreply@example.com
SPRING_MAIL_PASSWORDSMTP 密码/授权码xxxxxx
SPRING_MAIL_SMTP_AUTH是否启用 SMTP AUTHtrue
SPRING_MAIL_SMTP_STARTTLS_ENABLE是否启用 STARTTLSfalse
SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE是否启用 SMTP SSL 直连true
SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUSTSSL 信任主机(规避部分环境下证书链校验失败)smtp.mail.example
SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY验证码有效期(ISO-8601 Duration)PT10M
SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS发件人邮箱noreply@example.com
SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME发件人名称SkillHub

2.1 环境变量的后端绑定(源码证据)

这些变量在 application.yml 中通过${VAR:default}形式完成绑定:

  • Spring Mail 基础配置(application.yml 第 124-134 行):
spring: mail: host: ${SPRING_MAIL_HOST:localhost} port: ${SPRING_MAIL_PORT:25} username: ${SPRING_MAIL_USERNAME:} password: ${SPRING_MAIL_PASSWORD:} properties: mail: smtp: auth: ${SPRING_MAIL_SMTP_AUTH:false} starttls: enable: ${SPRING_MAIL_SMTP_STARTTLS_ENABLE:false}

注意:若你未配置任何 SMTP 变量,后端默认按localhost:25、无认证尝试发信,因此生产环境务必显式配置。

  • 密码重置业务配置(application.yml 第 166-169 行):
password-reset: code-expiry: ${SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY:PT10M} email-from-address: ${SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS:noreply@skillhub.local} email-from-name: ${SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME:SkillHub}
  • 配置类默认值(PasswordResetProperties.java):codeExpiry默认Duration.ofMinutes(10)(即PT10M)、emailFromAddress默认noreply@skillhub.local、emailFromName默认SkillHub,与 YAML 中的默认值一致。

  • Compose 透传(compose.release.yml 第 138-148 行):server服务将上述SPRING_MAIL_*与SKILLHUB_AUTH_PASSWORD_RESET_*全部映射为容器环境变量,其中SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY默认PT10M,FROM_ADDRESS默认noreply@skillhub.local,FROM_NAME默认SkillHub。

2.2 端口模式与取值说明

  • 本文统一按465 + SSL配置,不再展开587 + STARTTLS方案。
  • 使用465时配置:STARTTLS=false、SSL_ENABLE=true。
  • 若出现PKIX path building failed/SSLHandshakeException,可尝试增加SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=<SMTP_HOST>(本地联调常用)。
  • 生产环境默认不建议配置SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST,仅在证书链异常时临时启用。
  • SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY支持如PT5M、PT10M、PT30M等 ISO-8601 Duration 写法;邮件正文中会按codeExpiry.toMinutes()提示"验证码在 N 分钟内有效"(最短按 1 分钟计,见 PasswordResetService.java 第 249-253 行)。

仓库内置的环境模板 .env.release.example(第 178-189 行)给出了另一组可参考写法:SPRING_MAIL_PORT=587、STARTTLS_ENABLE=true、SSL_ENABLE=false,即587 + STARTTLS模式。两种端口模式按需二选一,务必保持STARTTLS与SSL_ENABLE与所选端口匹配。

3. 配置方案速查(推荐)

方案 A:通用 SMTP 邮箱(本地直连真实邮箱)

SPRING_MAIL_HOST=smtp.mail.example SPRING_MAIL_PORT=465 SPRING_MAIL_USERNAME=mailer@example.com SPRING_MAIL_PASSWORD=your-smtp-app-password SPRING_MAIL_SMTP_AUTH=true SPRING_MAIL_SMTP_STARTTLS_ENABLE=false SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=true SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=smtp.mail.example SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY=PT10M SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=mailer@example.com SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=your-from-name

本地export示例写法:

export SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=smtp.mail.example export SPRING_MAIL_HOST=smtp.mail.example export SPRING_MAIL_PORT=465 export SPRING_MAIL_USERNAME=mailer@example.com export SPRING_MAIL_PASSWORD=your-smtp-app-password export SPRING_MAIL_SMTP_AUTH=true export SPRING_MAIL_SMTP_STARTTLS_ENABLE=false export SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=true export SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY=PT10M export SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=mailer@example.com export SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=your-from-name

方案 B:MailHog(本地联调推荐)

SPRING_MAIL_HOST=127.0.0.1 SPRING_MAIL_PORT=1025 SPRING_MAIL_USERNAME= SPRING_MAIL_PASSWORD= SPRING_MAIL_SMTP_AUTH=false SPRING_MAIL_SMTP_STARTTLS_ENABLE=false SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=false SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=noreply@skillhub.local SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=SkillHub

MailHog 无需认证、不加密,直接以127.0.0.1:1025接收邮件,并在8025端口提供 Web UI 查看收件箱。

方案 C:线上部署(465 端口示例)

SPRING_MAIL_HOST=smtp.mail.example SPRING_MAIL_PORT=465 SPRING_MAIL_USERNAME=mailer@example.com SPRING_MAIL_PASSWORD=your-smtp-app-password SPRING_MAIL_SMTP_AUTH=true SPRING_MAIL_SMTP_STARTTLS_ENABLE=false SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=true SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=smtp.mail.example SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY=PT10M SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=mailer@example.com SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=your-from-name

线上建议将SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST留空,使用规范 CA 证书链;如需企业内网自签证书,见本文 7.6 节说明。

4. 单机交付(Compose)配置步骤

适用于生产/预发布环境,使用compose.release.yml+.env.release。

  1. 复制环境模板(若尚未创建):
cp .env.release.example .env.release
  1. 编辑.env.release,填写 SMTP 变量:
SPRING_MAIL_HOST=smtp.mail.example SPRING_MAIL_PORT=465 SPRING_MAIL_USERNAME=mailer@example.com SPRING_MAIL_PASSWORD=your-smtp-app-password SPRING_MAIL_SMTP_AUTH=true SPRING_MAIL_SMTP_STARTTLS_ENABLE=false SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=true SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=smtp.mail.example SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY=PT10M SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=mailer@example.com SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=your-from-name
  1. 重启后端容器使配置生效:
docker compose --env-file .env.release -f compose.release.yml up -d server
  1. 查看后端日志确认启动正常:
docker compose --env-file .env.release -f compose.release.yml logs -f server

提示:仓库的发布配置校验脚本 scripts/validate-release-config.sh(第 311-312 行)会对SPRING_MAIL_USERNAME/SPRING_MAIL_PASSWORD执行reject_patterns检查,拒绝TODO_*、todo_*、replace*等占位符,防止把占位值带上生产环境。

5. 本地开发配置与验证

5.1 一次性临时生效(推荐)

适合当前终端临时测试,重开终端后失效:

SPRING_MAIL_HOST=smtp.mail.example \ SPRING_MAIL_PORT=465 \ SPRING_MAIL_USERNAME=mailer@example.com \ SPRING_MAIL_PASSWORD=your-smtp-app-password \ SPRING_MAIL_SMTP_AUTH=true \ SPRING_MAIL_SMTP_STARTTLS_ENABLE=false \ SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=true \ SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=smtp.mail.example \ SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY=PT10M \ SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=mailer@example.com \ SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=your-from-name \ make dev-server

5.2 长期生效(shell 配置)

如果写入~/.zshrc,请注意:

  • 必须source ~/.zshrc或重开终端后变量才会生效;
  • 需要在同一个终端启动make dev-server。

可先确认变量是否在当前 shell 中:

env | rg '^(SPRING_MAIL_|SKILLHUB_AUTH_PASSWORD_RESET_)'

5.3 推荐联调方式(MailHog)

如果只是本地验证验证码链路,建议用 MailHog 作为本地 SMTP 服务:

  1. 启动 MailHog:
docker run -d --name skillhub-mailhog \ -p 1025:1025 \ -p 8025:8025 \ mailhog/mailhog
  1. 启动依赖服务(Postgres/Redis):
make dev
  1. 启动后端时注入 SMTP 环境变量(示例):
SPRING_MAIL_HOST=127.0.0.1 \ SPRING_MAIL_PORT=1025 \ SPRING_MAIL_USERNAME= \ SPRING_MAIL_PASSWORD= \ SPRING_MAIL_SMTP_AUTH=false \ SPRING_MAIL_SMTP_STARTTLS_ENABLE=false \ SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE=false \ SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS=noreply@skillhub.local \ SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME=SkillHub \ make dev-server
  1. 打开 MailHog Web UI 查看邮件:
http://localhost:8025
  1. 在 SkillHub 页面验证流程:
  • 打开/reset-password;
  • 输入邮箱并点击"发送验证码";
  • 在 MailHog 中查看验证码邮件;
  • 输入邮箱 + 验证码 + 新密码完成重置。
  1. 也可使用接口做快速验证(示例):
curl -X POST http://localhost:8080/api/v1/auth/local/password-reset/request \ -H 'Content-Type: application/json' \ -d '{"email":"your-email@example.com"}'

对应后端端点定义在 LocalAuthController.java:

  • POST /api/v1/auth/local/password-reset/request(第 118-123 行):发起重置请求,限流类别auth-password-reset-request;
  • POST /api/v1/auth/local/password-reset/confirm(第 125-130 行):校验验证码并更新密码,限流类别auth-password-reset-confirm。

6. 功能验证(验证码邮件)

6.1 用户自助找回

在/reset-password页面点击"发送验证码"后,系统会尝试发送验证码邮件。

说明:

  • 为防止账号枚举,自助接口总是返回通用成功提示(源码中"ineligible"邮箱直接 return,不暴露账号是否存在);
  • 即使邮件发送失败,接口也可能返回成功;请结合后端日志确认实际发送结果(服务端成功发送会记录Password reset verification code sent to ...,失败则记录Failed to send password reset verification code to ...,见 PasswordResetService.java 第 229-238 行)。

6.2 管理员触发重置

管理员在用户管理页触发"重置密码"时,系统会强制发送验证码;若 SMTP 发送失败,会返回错误(便于运维排障)。对应端点:

  • 后端:POST /api/v1/admin/users/{userId}/password-reset,见 UserManagementController.java 第 85-93 行;
  • 服务实现:adminTriggerPasswordReset中调用sendVerificationCodeEmail(email, code, true),failOnError=true时发送失败直接抛出error.auth.password.reset.email.failed(PasswordResetService.java 第 102-127 行)。

6.3 自动化测试佐证

仓库的 PasswordResetServiceTest.java 覆盖了关键链路:

  • 合法用户请求时保存PasswordResetRequest并调用mailSender.send(...);
  • SMTP 抛异常时自助请求仍正常返回(verify(resetRequestRepository).save(...)后不再抛出);
  • 邮箱为空、格式非法、账号不存在时均不触发发信(verifyNoInteractions);
  • 系统内置账号(如builtin-skill-publisher)不可发起密码重置;
  • 验证码不匹配时confirm拒绝执行。

7. 常见问题排查

7.1 认证失败(535 Authentication failed)

排查方向:

  • 用户名/密码是否正确;
  • 邮箱服务是否要求"客户端授权码"而非登录密码;
  • 发件账号是否已开启 SMTP 服务。

7.2 连接超时或拒绝连接

排查方向:

  • 主机到 SMTP 服务端口465是否可达;
  • 安全组/防火墙是否放行出站连接;
  • SMTP 服务地址是否填写正确。

7.3 本地明明配置了变量但不生效

排查方向:

  • 是否只是编辑了~/.zshrc但没有source ~/.zshrc;
  • 启动后端的终端是否与配置变量的终端是同一个;
  • 8080是否被旧进程占用,导致新进程没启动成功。

可执行以下命令快速检查:

# 查看 8080 是否被旧进程占用 lsof -nP -iTCP:8080 -sTCP:LISTEN # 查看当前 shell 是否有 SMTP 环境变量 env | rg '^(SPRING_MAIL_|SKILLHUB_AUTH_PASSWORD_RESET_)'

7.4 发件人被拒绝

排查方向:

  • SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS是否与 SMTP 账号一致或已验证;
  • 邮箱服务是否限制别名发件。

7.5 健康检查是否校验 SMTP

默认配置下,邮件健康检查关闭,不会因为 SMTP 不可达导致health失败——这是刻意设计,避免 SMTP 故障影响服务可用性判定(见 application.yml 第 311-313 行:health.mail.enabled: ${MANAGEMENT_HEALTH_MAIL_ENABLED:false})。

若需要将 SMTP 连通性纳入健康检查,可设置:

MANAGEMENT_HEALTH_MAIL_ENABLED=true

7.6 SMTP 报PKIX path building failed(证书链校验失败)

典型日志:

  • SSLHandshakeException
  • unable to find valid certification path to requested target

处理建议(本地联调):

SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST=smtp.mail.example

然后重启后端,再触发一次"发送验证码"。

补充:

  • 该配置用于指定信任主机(绕过证书链校验),适合本地排障与联调;
  • 生产环境默认不建议长期启用该配置,更推荐使用规范 CA 证书链,或将企业 CA 导入 Java truststore。

8. 安全建议

  • 不要把 SMTP 密码提交到仓库;仅写入受控的.env.release或密钥管理系统(配合 scripts/validate-release-config.sh 的占位符校验可提前拦截误提交);
  • 使用专用发信账号,避免使用个人邮箱主密码(优先使用邮箱服务提供的"客户端授权码"或"SMTP 专用密码");
  • 生产环境建议定期轮换 SMTP 授权码。

9. 相关文件索引

  • 本指南依据:docs/19-smtp-password-reset-email-setup.md
  • 环境模板:.env.release.example(第 178-189 行为 SMTP 段)
  • 发布编排:compose.release.yml(第 138-148 行为 SMTP 变量透传)
  • 后端配置:server/skillhub-app/src/main/resources/application.yml(Spring Mail 绑定与 password-reset 业务配置)
  • 业务配置类:PasswordResetProperties.java
  • 核心服务:PasswordResetService.java
  • 自助端点:LocalAuthController.java
  • 管理员端点:UserManagementController.java
  • 前端页面:web/src/pages/reset-password.tsx
  • 单元测试:PasswordResetServiceTest.java
  • 发布校验:scripts/validate-release-config.sh
  • 人工智能
  • AI Agent
  • AI 技能
  • 后端
  • 前端

【免费下载链接】skillhub

Self-hosted, open-source agent skill registry for enterprises. Publish & version skill packages, govern with RBAC and audit logs, deploy on-premise with Docker or Kubernetes.

项目地址:https://gitcode.com/gh_mirrors/sk/skillhub
点击查看免费下载

相关推荐

上一篇:终极NGA论坛优化指南:5分钟打造个性化高效浏览体验
下一篇:5分钟掌握X-AnyLabeling:AI智能标注工具快速入门指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询