""" 邮件服务 提供邮箱验证码发送功能,基于 SMTP 协议 """ import os import random import logging import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from typing import Optional logger = logging.getLogger(__name__) # 邮件配置(从环境变量读取) SMTP_HOST = os.getenv("SMTP_HOST", "smtp.qq.com") SMTP_PORT = int(os.getenv("SMTP_PORT", "465")) SMTP_USER = os.getenv("SMTP_USER", "") SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "") # QQ邮箱授权码 SMTP_FROM_NAME = os.getenv("SMTP_FROM_NAME", "智创空间") SMTP_USE_SSL = os.getenv("SMTP_USE_SSL", "true").lower() == "true" # 验证码有效期(秒) EMAIL_CODE_TTL = 300 # 5分钟 # 同一邮箱发送间隔(秒) EMAIL_SEND_INTERVAL = 60 def _send_email(to_email: str, subject: str, html_content: str) -> bool: """发送邮件,返回是否成功""" if not SMTP_USER or not SMTP_PASSWORD: logger.warning("未配置 SMTP_USER 或 SMTP_PASSWORD,邮件发送跳过(开发模式)") return True # 开发模式下直接返回成功 try: msg = MIMEMultipart("alternative") msg["Subject"] = subject msg["From"] = f"{SMTP_FROM_NAME} <{SMTP_USER}>" msg["To"] = to_email part = MIMEText(html_content, "html", "utf-8") msg.attach(part) if SMTP_USE_SSL: server = smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, timeout=10) else: server = smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=10) server.starttls() server.login(SMTP_USER, SMTP_PASSWORD) server.sendmail(SMTP_USER, [to_email], msg.as_string()) server.quit() logger.info(f"邮件发送成功: to={to_email}, subject={subject}") return True except Exception as e: logger.error(f"邮件发送失败: to={to_email}, error={e}") return False def _build_code_email(code: str, scene: str) -> tuple[str, str]: """构建验证码邮件内容,返回 (subject, html)""" scene_map = { "register": "注册", "login": "登录", "reset_password": "重置密码", } scene_name = scene_map.get(scene, "验证") subject = f"【智创空间】{scene_name}验证码" html = f"""
您正在进行{scene_name}操作,验证码为:
验证码有效期 5 分钟,请勿泄露给他人。
如非本人操作,请忽略此邮件。