如何在Python中修改multipart类型.eml邮件的链接内容
解决EML文件中Multipart邮件的HTTP链接替换问题
你的核心问题在于原代码没有正确处理多层嵌套的Multipart邮件结构,也没考虑HTML格式的邮件内容,同时忽略了Python字符串不可变的特性。以下是修正后的完整方案:
原代码的关键问题
- 未递归处理嵌套的Multipart结构(复杂新闻通讯类邮件通常有多层嵌套的内容部分)
get_payload()未指定具体的邮件部分对象,且replace操作未赋值(Python字符串是不可变类型,replace会返回新字符串,不赋值则修改无效)- 未区分文本类型(纯文本/HTML),直接修改顶级邮件的payload会破坏Multipart结构
修正后的代码
import glob from email import policy from email.parser import BytesParser def process_part(part): # 如果是Multipart类型,递归处理每个子部分 if part.is_multipart(): for sub_part in part.get_payload(): process_part(sub_part) return # 只处理纯文本或HTML格式的内容 content_type = part.get_content_type() if content_type not in ("text/plain", "text/html"): return # 获取内容并进行链接替换 try: # 优先用get_content()获取解码后的文本 text = part.get_content() modified_text = text.replace("http", "hxxp").replace("https", "hxxps") # 将修改后的内容设置回邮件部分,保留原编码 part.set_content(modified_text, subtype=content_type.split("/")[-1], charset=part.get_content_charset()) except Exception as e: print(f"处理邮件部分出错: {e}") def change_URL_in_EML(eml_path): for email_path in glob.glob(eml_path): with open(email_path, 'rb') as fp: msg = BytesParser(policy=policy.default).parse(fp) # 处理邮件的所有部分 process_part(msg) # 保存修改后的邮件,替换成你的目标路径 output_path = f"modified_{email_path}" with open(output_path, 'wb') as wp: wp.write(msg.as_bytes()) # 调用示例,替换成你的EML文件路径,比如"*.eml" change_URL_in_EML("*.eml")
代码说明
- 递归处理Multipart:通过
process_part函数递归遍历所有嵌套的邮件部分,确保不会遗漏任何文本内容 - 区分内容类型:只处理
text/plain和text/html类型的内容,避免修改图片、附件等非文本部分 - 正确处理字符串修改:将
replace后的新字符串赋值给modified_text,再通过set_content设置回邮件部分 - 保留原编码:使用
part.get_content_charset()获取原邮件的编码,避免出现乱码问题 - 安全处理异常:添加异常捕获,避免单个邮件部分处理失败导致整个程序崩溃
测试验证
用包含HTML内容的复杂Multipart邮件测试时,HTML中的<a href="https://example.com">会被替换为<a href="hxxps://example.com">,纯文本部分的链接也会同步替换,同时保留原邮件的格式和结构。
内容的提问来源于stack exchange,提问作者Andrew Kier
相关产品推荐
相关产品推荐

