feat: v3.1 - 用户密码管理和邮箱验证功能

新增功能:
1. 修改密码功能
   - 用户可以修改自己的密码
   - 需要验证旧密码
   - 新密码至少6位且不能与旧密码相同

2. 邮箱绑定功能
   - 用户可以绑定/修改邮箱
   - 邮箱格式验证和唯一性检查
   - 修改邮箱后需要重新验证

3. 邮箱验证功能
   - 发送验证邮件(24小时有效)
   - 点击邮件链接完成验证
   - 验证状态显示

技术实现:
- 新增4个数据库字段(email_verified等)
- 封装邮件发送工具(utils/email_sender.py)
- 新增5个API接口
- 新增修改密码页面
- 集成邮箱管理到个人中心

文件变更:
- 修改:app.py, models.py, base_new.html, profile.html
- 新增:change_password.html, email_sender.py, migrate_email_verification.py
- 文档:server-update.md, SERVER_RESTART_GUIDE.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Jowe
2026-02-07 23:26:02 +08:00
parent 1be1f35568
commit c61969dfc9
9 changed files with 1242 additions and 1 deletions

73
utils/email_sender.py Normal file
View File

@@ -0,0 +1,73 @@
"""
邮件发送工具模块
支持发送验证邮件、通知邮件等
"""
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
import logging
logger = logging.getLogger(__name__)
class EmailSender:
"""邮件发送器"""
def __init__(self):
"""初始化邮件配置"""
self.smtp_server = os.environ.get('SMTP_SERVER', 'smtp.gmail.com')
self.smtp_port = int(os.environ.get('SMTP_PORT', '587'))
self.smtp_user = os.environ.get('SMTP_USER', '')
self.smtp_password = os.environ.get('SMTP_PASSWORD', '')
self.from_email = os.environ.get('FROM_EMAIL', self.smtp_user)
self.from_name = os.environ.get('FROM_NAME', 'ZJPB')
def send_email(self, to_email, subject, html_content, text_content=None):
"""
发送邮件
Args:
to_email: 收件人邮箱
subject: 邮件主题
html_content: HTML格式邮件内容
text_content: 纯文本格式邮件内容(可选)
Returns:
bool: 发送是否成功
"""
try:
# 检查配置
if not self.smtp_user or not self.smtp_password:
logger.error('邮件配置不完整请设置SMTP_USER和SMTP_PASSWORD环境变量')
return False
# 创建邮件对象
message = MIMEMultipart('alternative')
message['From'] = f'{self.from_name} <{self.from_email}>'
message['To'] = to_email
message['Subject'] = Header(subject, 'utf-8')
# 添加纯文本内容
if text_content:
text_part = MIMEText(text_content, 'plain', 'utf-8')
message.attach(text_part)
# 添加HTML内容
html_part = MIMEText(html_content, 'html', 'utf-8')
message.attach(html_part)
# 连接SMTP服务器并发送
with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:
server.starttls() # 启用TLS加密
server.login(self.smtp_user, self.smtp_password)
server.send_message(message)
logger.info(f'邮件发送成功: {to_email}')
return True
except Exception as e:
logger.error(f'邮件发送失败: {str(e)}')
return False