Python3.6中如何彻底删除邮件附件而非仅清空MIME部分?
彻底删除邮件中的指定MIME附件(Python 3.6)
在归档旧邮件时,若使用clear()方法删除附件,只会清空MIME部件的内容,该部件仍会留在邮件结构中并被识别为text/plain类型,导致Thunderbird、Gmail等客户端显示异常。要解决这个问题,需要从父multipart部件中彻底移除目标附件部件,而不是仅清空内容。
问题复现示例
示例代码
from email import policy from email.parser import BytesParser from email.iterators import _structure with open(eml_path, 'rb') as fp: msg = BytesParser(policy=policy.SMTP).parse(fp) print(_structure(msg)) for part in msg.walk(): cd = part.get_content_disposition() if cd is not None: part.clear() print(_structure(msg))
原始邮件结构
multipart/mixed multipart/alternative text/plain multipart/related text/html image/png image/png text/plain text/plain
使用clear()后的结构(残留空部件)
multipart/mixed multipart/alternative text/plain multipart/related text/html text/plain text/plain text/plain text/plain
解决方案:从父部件中移除目标附件
核心思路是:找到需要删除的附件部件,然后从其所属的父multipart部件的parts列表中移除该部件,而非仅清空内容。
修改后的代码
from email import policy from email.parser import BytesParser from email.iterators import _structure with open(eml_path, 'rb') as fp: msg = BytesParser(policy=policy.SMTP).parse(fp) print("原始邮件结构:") print(_structure(msg)) # 先收集所有需要删除的部件及其父部件,避免遍历过程中修改列表导致异常 to_remove = [] for part in msg.walk(): cd = part.get_content_disposition() if cd is not None: parent = part.get_parent() if parent is not None: to_remove.append((parent, part)) # 批量从父部件中移除目标附件 for parent, part in to_remove: parent.parts.remove(part) print("\n删除附件后的邮件结构:") print(_structure(msg))
处理后的预期结构
multipart/mixed multipart/alternative text/plain multipart/related text/html
说明
- 先收集待删除的
(父部件, 目标部件)对,是因为直接在walk()遍历过程中修改部件列表会导致遍历异常 - 使用
get_parent()获取部件所属的父multipart,调用parent.parts.remove(part)即可彻底移除该附件部件,不会留下空的MIME条目,解决客户端显示问题
内容的提问来源于stack exchange,提问作者Bangaio
相关产品推荐
相关产品推荐

