Python EmailMessage发送邮件附件时内容为文件名而非写入内容问题
问题结论
不存在“同一段代码不能同时完成文件写入、附件添加发送”的限制,你拿到错误附件的核心原因是文件读写逻辑顺序写反了,和EmailMessage模块本身无关。
你的代码存在两个明确错误:
- 用
w+模式打开文件时,会立刻清空文件原有内容,初始文件指针停在文件开头。你刚打开就调用f.read(),此时文件已经被清空,只能读到空字符串。 - 调用
f.write('hey')写入内容后,文件指针会移动到写入内容的末尾,你没有将指针重置到文件开头,也没有重新读取写入后的内容,最终传给add_attachment的根本不是你写入的"hey"。
你收到的附件显示为文件名,本质是传入的附件内容为空时,邮件客户端做的异常兼容显示。
两种可行实现方案
方案1:无需本地留存文件,直接构造附件
如果你只是想发送一个文件名为test.txt、内容为"hey"的附件,完全不需要在本地创建实体文件,直接把内容编码后传入即可:
import smtplib from email.message import EmailMessage msg = EmailMessage() msg['from'] = "blah_blah@gmail.com" msg['To'] = "blah_blah@gmail.com" msg['Subject'] = "This is TEST" file_name = "test.txt" content = "hey" msg.add_attachment( content.encode('utf-8'), maintype='text', subtype='plain', filename=file_name ) # SMTP连接推荐用with上下文管理,自动释放连接 with smtplib.SMTP(host='blah_blah_server.net', port=100) as s: s.send_message(msg)
方案2:需要本地留存test.txt,再读取文件发附件
如果你确实需要先把内容写入本地磁盘留存,再发送该文件,调整读写顺序即可,写完内容后要先把文件指针重置到开头再读取:
import smtplib from email.message import EmailMessage msg = EmailMessage() msg['from'] = "blah_blah@gmail.com" msg['To'] = "blah_blah@gmail.com" msg['Subject'] = "This is TEST" file_name = "test.txt" with open(file_name, 'w+') as f: f.write('hey') # 重置指针到文件开头,才能读取到刚写入的内容 f.seek(0) file_data = f.read() msg.add_attachment( file_data.encode('utf-8'), maintype='text', subtype='plain', filename=file_name ) with smtplib.SMTP(host='blah_blah_server.net', port=100) as s: s.send_message(msg)
额外注意点
- 所有IO操作(文件读写、SMTP连接等)都推荐用
with上下文管理器,会自动处理连接关闭、缓冲区刷新,避免资源泄漏或者内容未写入磁盘的问题。 w+是覆盖写入模式,每次打开文件都会清空原有内容,如果需要在文件末尾追加内容,要改用a+模式。
内容的提问来源于stack exchange,提问作者SuperDummy
相关产品推荐
相关产品推荐

