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

如何将SMTP服务器状态保存到文件以实现免重复登录?

解决无法保存SMTP服务器状态以避免重复登录的问题

为什么pickle不可行?

SMTP对象包含SSLSocket这类与系统底层网络资源绑定的对象,这类实时连接状态无法被序列化(pickle),所以直接保存整个server实例必然报错。

可行方案

方案1:进程内复用连接

如果是在同一个进程内多次发送邮件,直接维护一个全局的SMTP对象,检测连接状态失效后再重新初始化:

import smtplib, ssl

class GmailSMTPManager:
    def __init__(self, user, password):
        self.user = user
        self.password = password
        self._server = None

    def get_server(self):
        # 检查连接是否存活
        if self._server is None:
            self._init_server()
        else:
            try:
                self._server.noop()  # 发送空命令检测连接状态
            except smtplib.SMTPServerDisconnected:
                self._init_server()
        return self._server

    def _init_server(self):
        self._server = smtplib.SMTP(host="smtp.gmail.com", port=587)
        self._server.ehlo()
        self._server.starttls(context=ssl.create_default_context())
        self._server.ehlo()
        self._server.login(user=self.user, password=self.password)

# 使用示例
manager = GmailSMTPManager("abc@gmail.com", "abcdefghijklmnop")
# 首次调用初始化并登录
server = manager.get_server()
server.sendmail("abc@gmail.com", "recipient@example.com", "邮件内容")
# 后续调用复用存活连接
server = manager.get_server()
server.sendmail("abc@gmail.com", "another@example.com", "另一封邮件")

方案2:保存登录凭证而非连接状态

SMTP连接本身有超时限制,即使能序列化保存,过一段时间也会失效。更可靠的方式是保存登录凭证,每次需要发邮件时重新建立连接(带状态检测):

import smtplib, ssl
import json
import os

# 保存凭证到本地文件
def save_credentials(user, password, filepath="gmail_creds.json"):
    with open(filepath, "w") as f:
        json.dump({"user": user, "password": password}, f)

# 加载本地凭证
def load_credentials(filepath="gmail_creds.json"):
    if os.path.exists(filepath):
        with open(filepath, "r") as f:
            return json.load(f)
    return None

# 获取可用的SMTP服务器连接
def get_active_smtp(credentials):
    server = smtplib.SMTP(host="smtp.gmail.com", port=587)
    try:
        server.noop()
    except smtplib.SMTPServerDisconnected:
        # 连接失效,重新登录
        server.ehlo()
        server.starttls(context=ssl.create_default_context())
        server.ehlo()
        server.login(credentials["user"], credentials["password"])
    return server

# 使用示例
# 首次运行保存凭证
save_credentials("abc@gmail.com", "abcdefghijklmnop")
# 后续运行加载凭证并获取连接
creds = load_credentials()
if creds:
    smtp_server = get_active_smtp(creds)
    smtp_server.sendmail("abc@gmail.com", "target@example.com", "测试邮件")

注意:Gmail用户建议使用应用专用密码(开启两步验证后可创建),而非邮箱原始密码,提升账号安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:27:47