发送带附件邮件时执行成功却报错,疑似重复处理最后文件
听起来这个问题挺挠人的——功能明明正常跑通了,结果每次都在最后一个文件上炸锅,还定位到是邮件处理的代码段,连单文件场景都中招。我来帮你捋捋几个最可能的原因和解决办法:
1. Windows路径转义的隐形坑(最常见)
Windows用反斜杠\表示路径,但在Python字符串里\是转义字符,比如\t会被解析成制表符、\U会触发Unicode转义,这会导致实际生成的路径和你写的完全不一样,最后触发FileNotFoundError。
解决办法:
- 用原始字符串:在路径前加
r,比如r'C:\Users\h\your_file.txt' - 或者用双反斜杠:
'C:\\Users\\h\\your_file.txt' - 更稳妥的是用
pathlib库处理路径,彻底规避转义问题:
from pathlib import Path # 正斜杠在Windows上也能正常工作 file_path = Path('C:/Users/h/your_file.txt') # 或者依然用反斜杠,配合原始字符串 file_path = Path(r'C:\Users\h\your_file.txt')
2. 邮件对象的重复引用或资源未释放
如果你是循环处理多文件发送邮件,很可能不小心在循环外保留了最后一个附件的引用,导致发送完成后代码重复访问它;或者打开文件时没正确关闭句柄,导致文件被占用,后续检查时误以为文件不存在。
正确的附件添加写法:
确保每次循环都新建邮件对象,并用with语句安全打开文件(自动释放句柄):
from pathlib import Path import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders file_list = [r'C:\Users\h\file1.txt', r'C:\Users\h\file2.txt'] for file_path in file_list: # 每次循环都新建邮件实例,避免交叉引用 msg = MIMEMultipart() msg['Subject'] = f"Attachment: {Path(file_path).name}" msg['From'] = "your_email@example.com" msg['To'] = "recipient@example.com" # 用with语句自动关闭文件句柄 with open(file_path, 'rb') as att: part = MIMEBase('application', 'octet-stream') part.set_payload(att.read()) encoders.encode_base64(part) # 只传文件名,避免路径混乱 part.add_header('Content-Disposition', f'attachment; filename="{Path(file_path).name}"') msg.attach(part) # 发送邮件 with smtplib.SMTP('smtp.example.com', 587) as server: server.starttls() server.login('your_email@example.com', 'your_password') server.send_message(msg)
3. 邮件库的隐式操作
一些封装过的邮件库(比如yagmail)可能会在发送后自动清理临时文件,如果你用了临时文件作为附件,发送后文件被删除,后续代码访问就会报错。如果是这种情况,要么使用持久化文件路径,要么在发送完成后再执行文件清理操作。
快速排查小技巧
- 打印实际路径:在添加附件前打印
file_path,确认路径和预期一致:
print(f"Processing file: {file_path}")
如果输出有乱码或缺失,就是转义问题。
- 捕获完整错误信息:在疑似报错的代码段加
try-except,打印完整路径和错误:
try: # 你怀疑有问题的邮件处理代码 except FileNotFoundError as e: print(f"Missing file path: {e.filename}") print(f"Full error details: {str(e)}")
这样能精准定位到底是哪个路径出了问题。
- 简化代码测试:把移动文件的代码暂时注释掉,只保留邮件发送逻辑,看单文件场景还会不会报错。如果不报错了,就是后续代码和邮件处理的交互问题;如果依然报错,就聚焦邮件代码本身。
内容的提问来源于stack exchange,提问作者Dane Looman
相关产品推荐
相关产品推荐

