Python执行MySQL交互后发送Gmail邮件触发SSL证书验证失败问题
问题根因
该证书校验错误是mysql-connector-python驱动的全局副作用导致:
驱动在建立连接的初始化流程中,会强制覆写进程级别的OpenSSL环境变量SSL_CERT_FILE、SSL_CERT_DIR,将CA证书搜索路径指向驱动自身打包的内置证书文件。这套内置证书库未包含Gmail SMTP服务STARTTLS握手所需的公共根CA证书,因此后续smtplib走TLS握手时,无法找到可信的根证书完成校验,抛出CERTIFICATE_VERIFY_FAILED错误。
当你移除所有MySQL相关代码时,驱动不会被加载执行,全局SSL环境变量不会被篡改,Python标准库ssl模块可以正常读取Ubuntu系统默认路径下的CA证书存储,邮件发送功能自然可以正常运行。
可行修复方案
选择任意一种方案即可解决问题:
- 方案1:备份并恢复SSL环境变量
在导入mysql.connector模块前,先备份当前系统的SSL证书路径相关环境变量;等MySQL连接完全关闭后,将环境变量还原为备份的原始值,再执行邮件发送逻辑。
核心修改代码示例:import os # 备份原始SSL环境变量 backup_cert_file = os.environ.get("SSL_CERT_FILE") backup_cert_dir = os.environ.get("SSL_CERT_DIR") import mysql.connector # 此处保留原有MySQL连接、查询、断开连接的全部逻辑 # mydb = mysql.connector.connect(...) # ... 查询、断开连接逻辑 ... # 恢复原始SSL环境变量 if backup_cert_file is None: os.environ.pop("SSL_CERT_FILE", None) else: os.environ["SSL_CERT_FILE"] = backup_cert_file if backup_cert_dir is None: os.environ.pop("SSL_CERT_DIR", None) else: os.environ["SSL_CERT_DIR"] = backup_cert_dir # 后续原有smtplib发邮件的代码无需修改 - 方案2:手动指定SSL上下文的CA证书路径
创建邮件TLS连接所用的SSL上下文时,直接显式指定Ubuntu系统默认的CA证书文件路径,绕开被驱动篡改的环境变量影响,无需调整MySQL相关逻辑。
仅需要将原有创建上下文的代码:
替换为:my_context = ssl.create_default_context()my_context = ssl.create_default_context(cafile="/etc/ssl/certs/ca-certificates.crt") - 方案3:替换MySQL驱动
如果业务代码没有强依赖mysql-connector-python的专属特性,可以更换为不修改全局环境变量的MySQL驱动,比如PyMySQL、mysqlclient,这类驱动不会篡改进程全局的SSL配置,不会触发这类跨模块的异常。
内容的提问来源于stack exchange,提问作者Rene Reitsma
相关产品推荐
相关产品推荐

