feat: 添加邮件功能第三阶段 - 密码重置

实现通过邮件自助重置密码功能:
- 新增发送密码重置邮件API (/api/forgot-password)
- 新增密码重置页面路由 (/reset-password/<token>)
- 新增确认密码重置API (/api/reset-password-confirm)

新增文件:
- templates/email/reset_password.html - 密码重置邮件模板
- templates/reset_password.html - 密码重置页面

修改文件:
- email_service.py - 添加密码重置相关函数
  - send_password_reset_email()
  - verify_password_reset_token()
  - confirm_password_reset()
- app.py - 添加密码重置相关API
- templates/login.html - 忘记密码支持两种方式:
  - 启用邮件功能:通过邮件自助重置
  - 未启用邮件:提交申请等待管理员审核

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-11 21:58:49 +08:00
parent de8edcb3a6
commit 93375b612f
5 changed files with 691 additions and 4 deletions

View File

@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin: 0; padding: 0; font-family: 'Microsoft YaHei', Arial, sans-serif; background-color: #f5f5f5;">
<table width="100%" cellpadding="0" cellspacing="0" style="background-color: #f5f5f5; padding: 30px 0;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background-color: #ffffff; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
<!-- 头部 -->
<tr>
<td style="background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); padding: 30px; border-radius: 10px 10px 0 0; text-align: center;">
<h1 style="color: #ffffff; margin: 0; font-size: 24px;">知识管理平台</h1>
<p style="color: rgba(255,255,255,0.9); margin: 10px 0 0 0; font-size: 14px;">密码重置验证</p>
</td>
</tr>
<!-- 内容 -->
<tr>
<td style="padding: 40px 30px;">
<p style="color: #333; font-size: 16px; margin: 0 0 20px 0;">
您好,<strong>{{ username }}</strong>
</p>
<p style="color: #666; font-size: 14px; line-height: 1.8; margin: 0 0 25px 0;">
我们收到了您的密码重置请求。请点击下方按钮重置您的密码。
</p>
<!-- 重置按钮 -->
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center" style="padding: 20px 0;">
<a href="{{ reset_url }}" style="display: inline-block; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); color: #ffffff; text-decoration: none; padding: 15px 40px; border-radius: 30px; font-size: 16px; font-weight: bold;">
重置密码
</a>
</td>
</tr>
</table>
<p style="color: #999; font-size: 12px; line-height: 1.8; margin: 25px 0 0 0;">
如果按钮无法点击,请复制以下链接到浏览器打开:
</p>
<p style="color: #e74c3c; font-size: 12px; word-break: break-all; background: #fff5f5; padding: 15px; border-radius: 5px; margin: 10px 0;">
{{ reset_url }}
</p>
<div style="background: #fff3e0; border-left: 4px solid #ff9800; padding: 15px; margin: 25px 0; border-radius: 0 5px 5px 0;">
<p style="color: #e65100; font-size: 13px; margin: 0;">
<strong>注意:</strong>此链接有效期为 30 分钟,过期后需要重新申请。
</p>
</div>
<p style="color: #999; font-size: 13px; margin: 20px 0 0 0;">
如果您没有申请过密码重置,请忽略此邮件,您的密码不会被修改。
</p>
</td>
</tr>
<!-- 底部 -->
<tr>
<td style="background: #f8f9fa; padding: 20px 30px; border-radius: 0 0 10px 10px; text-align: center;">
<p style="color: #999; font-size: 12px; margin: 0;">
此邮件由系统自动发送,请勿直接回复。
</p>
<p style="color: #ccc; font-size: 11px; margin: 10px 0 0 0;">
&copy; 知识管理平台
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>