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

Python连接Gmail SMTP服务器时TLS握手证书错误排查

Gmail SMTP TLS握手加载证书报错问题排查

问题代码及报错信息

import ssl, smtplib, email

def send_email(subject, body, sender, recipients, password):
    mml = email.message.EmailMessage()
    mml.set_content(body)
    mml['From'] = sender
    mml['To'] = ', '.join(recipients)
    mml['Subject'] = subject
    sslctx = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT)
    sslctx.verify_mode = ssl.CERT_REQUIRED
    assert sslctx.verify_mode == ssl.CERT_REQUIRED
    sslctx.load_verify_locations(cafile='crt.pem', capath='.')
    hdlr = smtplib.SMTP(host='smtp.gmail.com', port=587) # do not use SMTP_SSL
    hdlr.starttls(context=sslctx)
    hdlr.login('my-account-xxx@gmail.com', password)
    hdlr.sendmail(sender, recipients, mml.as_string())
    print("[INFO] Message sent!")

执行时触发报错:

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ssl.SSLError: [SSL] PEM lib (_ssl.c:3917)

用户疑问及解答

疑问1:SSLContext.load_cert_chain()是否要求调用者提供有效的keyfile参数?

你混淆了load_cert_chain和load_verify_locations两个方法:

  • load_cert_chain用于加载客户端自身的证书链和私钥,仅当服务器要求双向TLS验证时才需要调用。它的keyfile参数在需要加载私钥时是必须的,但你的场景是普通Gmail SMTP客户端,根本不需要调用这个方法。
  • 你代码中实际调用的是load_verify_locations,这个方法是用来指定信任的CA证书库,用于验证服务器证书,和load_cert_chain无关。

疑问2:crt.pem证书文件是否存在问题?

大概率存在问题:

  1. 证书类型错误:你下载的是Gmail SMTP服务器的叶子证书,但load_verify_locations需要的是信任的根CA证书(比如GTS Root R1),而非服务器本身的证书。
  2. 格式或路径问题:证书文件可能不是标准PEM格式,或者文件路径错误导致加载失败。
  3. 额外说明:Python的ssl模块默认已经信任主流CA颁发的证书(包括Gmail的),完全不需要手动指定cafile。

修正后的代码

import ssl, smtplib, email

def send_email(subject, body, sender, recipients, password):
    mml = email.message.EmailMessage()
    mml.set_content(body)
    mml['From'] = sender
    mml['To'] = ', '.join(recipients)
    mml['Subject'] = subject
    # 使用默认TLS上下文,自动加载系统信任的CA证书
    sslctx = ssl.create_default_context()
    sslctx.verify_mode = ssl.CERT_REQUIRED
    hdlr = smtplib.SMTP(host='smtp.gmail.com', port=587)
    hdlr.starttls(context=sslctx)
    hdlr.login('my-account-xxx@gmail.com', password)
    hdlr.sendmail(sender, recipients, mml.as_string())
    print("[INFO] Message sent!")

额外注意事项

  • 如果你的Gmail账号开启了两步验证,必须使用应用专用密码登录,不能用普通账号密码。
  • 若确实需要手动指定CA证书,确保下载的是根CA的PEM格式文件,且路径正确。

内容的提问来源于stack exchange,提问作者T.H.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 00:06:10