使用smtplib发送多附件时非Gmail邮箱接收异常问题求助
问题分析与解决方案
问题根源
你的代码在循环处理完所有附件后,额外执行了两行错误代码,导致邮件结构被破坏:
- 循环外的
part.add_header("Content-Disposition",f"attachment; filename= {attachments}",)会把整个附件列表转成字符串(比如['file1xxx.pdf', 'file2.pdf'])作为文件名,非Gmail客户端(如Outlook)解析时会误把这个字符串当成附件名,且丢失扩展名。 - 重复执行
message.attach(part)会再次添加最后一个附件,造成冗余,进一步干扰客户端的解析逻辑。
另外,用'attachments' in globals()判断附件存在完全没必要——你已经显式定义了这个变量,直接判断列表是否非空即可。
修正后的代码
import smtplib import os from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders import ssl sender_email = "sender@gmail.com" receiver_email = str(names[i]) # 注意:开启双因素认证的Gmail必须用【应用专用密码】,不是登录验证码 password = input("输入应用专用密码: ") subject = "Title" body = """Hi, This is the body of the email """ attachments = [f'file1{str(names[i])}.pdf', 'file2.pdf'] # 用f-string简化文件名拼接 # 创建多部分邮件并设置头信息 message = MIMEMultipart() message["From"] = sender_email message["To"] = receiver_email message["Subject"] = subject # 批量发送时建议用Bcc隐藏收件人,单个发送可省略此行 message["Bcc"] = receiver_email # 添加邮件正文 message.attach(MIMEText(body, "plain")) # 处理附件(直接判断列表是否非空) if attachments: for filename in attachments: # 用with语句安全打开文件,避免资源泄漏 with open(filename, "rb") as f: part = MIMEBase('application', "octet-stream") part.set_payload(f.read()) encoders.encode_base64(part) # 确保文件名正确解析 part.add_header( 'Content-Disposition', f'attachment; filename="{os.path.basename(filename)}"' ) message.attach(part) # 转换邮件为字符串 text = message.as_string() # 连接服务器发送邮件 context = ssl.create_default_context() with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server: server.login(sender_email, password) server.sendmail(sender_email, receiver_email, text)
额外注意事项
- Gmail双因素认证:必须使用Google账号安全设置中生成的应用专用密码,普通密码或登录验证码无法用于SMTP登录。
- 特殊文件名处理:如果文件名包含中文或非ASCII字符,需要用
email.header.Header处理编码,确保所有客户端正常显示:from email.header import Header part.add_header( 'Content-Disposition', f'attachment; filename="{Header(os.path.basename(filename), "utf-8").encode()}"' ) - 批量发送优化:循环发送时,建议把所有收件人放在
Bcc字段中,避免泄露收件人邮箱列表。
内容的提问来源于stack exchange,提问作者and_36100
相关产品推荐
相关产品推荐

