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

遍历DataFrame批量发邮件多次迭代后出现smtplib.SMTPServerDisconnected错误求助

解决遍历DataFrame发送邮件时的smtplib.SMTPServerDisconnected错误

我明白你在批量发送邮件时遇到了服务器断开连接的问题,这大概率是因为你每次循环都重复创建并关闭SMTP连接,频繁的连接/断开操作很容易触发邮件服务器(比如Gmail)的限制,导致连接被强制中断。另外你的代码里还有几处小问题需要修正,下面一步步来解决:

问题根源分析

  • 频繁创建销毁连接:每次循环都调用smtplib.SMTP_SSL()新建连接,发送后立刻server.quit()关闭,短时间内的这类操作会被服务器判定为异常行为,直接断开连接。
  • 循环逻辑漏洞:原代码中while i<=len(df)的i既没有初始化,也没有在循环内递增,会导致无限循环,进一步加重服务器连接压力。
  • 重复IO浪费:每次循环都重复读取同一个附件文件,虽然不影响功能,但会额外消耗IO资源。

修复后的完整代码

import pandas as pd
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header

filename = "my_excel.xlsx"
df = pd.read_excel(filename, sheet_name='Sheet1')
user = 'my_mail'
app_password = 'password'
host = 'smtp.gmail.com'
port = 465
subject = 'Proof'
attachment = "attachment.pdf"

# 提前读取附件内容,避免循环内重复IO操作
with open(attachment, 'rb') as f:
    attachment_content = f.read()
att_name = os.path.basename(attachment)

# 仅创建一次SMTP连接,复用连接发送所有邮件
server = smtplib.SMTP_SSL(host, port)
try:
    server.login(user, app_password)
    
    # 用iterrows()安全遍历DataFrame每一行
    for idx, row in df.iterrows():
        if row['Status'] == 'vencido':
            text = 'my_text'
            to = row['email']
            
            message = MIMEMultipart()
            message['From'] = Header(user)
            message['To'] = Header(to)
            message['Subject'] = Header(subject)
            
            content_txt = text
            message.attach(MIMEText(content_txt, 'plain', 'utf-8'))
            
            # 构造附件(复用提前读取的内容)
            att1 = MIMEText(attachment_content, 'base64', 'utf-8')
            att1['Content-Type'] = 'application/octet-stream'
            att1['Content-Disposition'] = f'attachment; filename="{att_name}"'
            message.attach(att1)
            
            # 发送邮件
            server.sendmail(user, to, message.as_string())
            print(f"邮件已成功发送到 {to}")
            
finally:
    # 无论是否出现异常,最后统一关闭连接
    server.quit()

关键改进说明

  • 复用SMTP连接:在循环外创建一次连接并登录,用它完成所有邮件发送后再关闭,大幅减少连接次数,避免触发服务器限制。
  • 安全遍历DataFrame:使用iterrows()遍历每一行,比直接索引更安全,同时解决了原代码中i未初始化的问题。
  • 优化附件读取:提前读取一次附件内容,循环内直接复用,节省IO资源。
  • 异常安全处理:用try...finally确保连接一定会被正确关闭,避免资源泄漏。

额外建议

如果需要发送的邮件数量非常多(比如几百上千封),建议在每发送10-20封后加入短暂休眠(import time; time.sleep(2)),避免给服务器造成过大压力;另外Gmail用户需要确保已开启2FA并使用App密码登录,或者开启“不太安全的应用访问”(后者不推荐),否则会被拒绝登录。

内容的提问来源于stack exchange,提问作者Andrés Reyes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:31:14