You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

yagmail使用GMail OAuth2认证数天后失效的解决方法

问题根因

抛出HTTP Error 400: Bad Request的核心原因是你存储的Google OAuth2刷新令牌(refresh_token)已失效,和yagmail库本身的凭证刷新逻辑无关。Google侧会在特定规则下主动作废已签发的refresh_token,你遇到的每隔数天固定复现故障的情况,绝大多数是因为你的OAuth应用处于「测试」发布状态——测试状态下Google签发的所有refresh_token有效期固定为7天,到期直接作废,和你描述的故障周期完全匹配。

其他会触发refresh_token非预期失效的常见场景:

  • 同一Google账号对同一OAuth客户端累计签发的有效refresh_token超过50个,最早生成的token会被自动回收
  • 账号修改密码、触发Google安全风控(如非常用IP连续登录、判定为异常发信行为),所有已签发的refresh_token会被批量作废
  • 授权流程未正确申请离线权限,拿到的是短效refresh_token
解决方案

按以下步骤调整即可彻底解决定期需要手动重生成凭证的问题:

1. 将OAuth应用切换为生产发布状态

这是解决7天固定过期问题的核心操作:

  • 登录Google Cloud控制台,进入对应项目的「API和服务」-「OAuth同意屏幕」页面
  • 如果当前应用状态显示为「测试中」,直接点击「发布应用」按钮,将状态切换为「生产中」
  • 仅内部使用、只申请https://mail.google.com/发信权限的应用不需要提交Google审核,切换状态后立即生效,签发的refresh_token不再有7天有效期限制

2. 重新生成长期有效的refresh_token

切换应用状态后,重新走一次OAuth授权流程生成新的凭证文件,注意授权请求必须携带两个参数,否则拿不到长期有效token:

  • access_type=offline:告知Google需要返回可用于后台自动刷新凭证的refresh_token
  • prompt=consent:强制弹出授权确认页,避免Google返回之前缓存的旧短效token

用新流程生成的credentials.json替换服务器上的旧文件即可,正常使用场景下这个refresh_token不会自动过期。

3. 可选兜底优化

可以在发信逻辑里加一层异常捕获,避免极端风控场景下业务完全无感知:

import yagmail
from urllib.error import HTTPError

def send_with_yagmail(self):
    try:
        yag = yagmail.SMTP(self.our_email, oauth2_file="/<path_to>/credentials.json")
        yag.send(self.to_email, self.message_subject, contents=self.message_body)
    except HTTPError as e:
        if e.code == 400:
            # 可在此处接入告警,通知管理员及时更新凭证
            raise RuntimeError("Gmail发信认证失效,请更新OAuth2凭证") from e
注意事项
  • 不要在多套环境(本地、测试机、生产机)反复对同一个客户端/账号触发授权生成新的refresh_token,单账号单客户端最多保留50个有效refresh_token,超额后旧token会被自动作废
  • 生产环境尽量固定发信服务的出口IP,避免频繁跨地域登录触发Google安全风控
  • 不要用该Gmail账号发送垃圾邮件、短时间批量发信,否则会触发风控直接作废所有凭证

内容的提问来源于stack exchange,提问作者mircealungu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:30:10