Flask发送QQ邮箱验证码成功的关键在于正确配置授权码、端口与加密方式:MAIL_PASSWORD必须为QQ邮箱SMTP授权码而非登录密码;TLS配587端口或SSL配465端口,二者不可同时启用;需确保mail.init_app(app)完成初始化,并用redis缓存验证码。

Flask 发送 QQ 邮箱验证码,核心不是“能不能发”,而是“配置对不对、授权码用没用对、端口和加密方式配不匹配”。绝大多数失败都卡在这三步,而不是代码逻辑。
QQ邮箱必须用授权码,不能用登录密码
这是最常踩的坑:在 config.py 里填 MAIL_PASSWORD 时,直接填了 QQ 账号密码——这必然失败。
- 必须去 QQ 邮箱网页版 → 设置 → 账户 → “POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务” → 开启 SMTP 服务
- 开启后会弹出二维码或短信验证,通过后生成一串 16 位字母数字组合,这就是 授权码
-
MAIL_PASSWORD的值必须是这个授权码,不是邮箱密码,也不是手机验证码
端口和加密方式必须严格对应
QQ 邮箱只支持两种组合,填错一个就连接超时或被拒绝:
- 用
MAIL_USE_TLS = True→MAIL_PORT = 587 - 用
MAIL_USE_SSL = True→MAIL_PORT = 465 - 二者不能同时为
True;也不能都为False(QQ 邮箱不接受明文) -
MAIL_SERVER必须是"smtp.qq.com",大小写敏感,不能漏掉smtp.
发送逻辑里别漏掉 app_context 或初始化顺序
如果你在视图函数里调用 mail.send() 报 RuntimeError: working outside of application context,说明 Flask-Mail 没绑定到 app 实例上。
- 确保
exts.py中创建了mail = Mail() - 确保
app.py或工厂函数里调用了mail.init_app(app) - 测试时如果用
flask shell手动发邮件,得先手动进上下文:with app.app_context():<br> mail.send(msg)
验证码生成和存储建议用缓存而非数据库
邮箱验证码本质是临时凭证,有效期短(通常 5–10 分钟),写数据库反而增加延迟和冗余。
- 优先用
redis或memcache:以email为 key,captcha+ 过期时间存 value - 避免用
random.sample(string.digits*4, 4)这种写法——string.digits*4是 "01234567890123456789...",重复元素可能导致sample报错;改用random.choices(string.digits, k=6)更安全 - 发送成功后记得返回明确状态(如 JSON
{"code": 0, "msg": "已发送"}),前端才好控制倒计时按钮禁用
真正容易被忽略的是授权码的时效性和使用限制:一个授权码只能用于一个邮箱账户,且一旦在其他设备重复启用 SMTP,旧授权码会立即失效。每次调试建议重新生成一个,别复用。



















