【实用教程】python 批量解析 EML 邮件文件 存成txt ,可以利用 AI 辅助快速生成年终总结
【实用教程】批量解析EML邮件文件,AI辅助快速生成年终总结
在年底撰写工作总结时,邮件记录是最真实的工作轨迹凭证。手动整理数十上百封邮件不仅耗时,还容易遗漏关键信息。本文将分享一个Python脚本,可批量解析EML格式邮件,自动汇总发件人、收件人、主题、正文等核心信息,生成结构化的文本报告,直接投喂AI即可快速生成高质量年终总结。
一、教程核心价值
- 解放双手:批量处理任意数量EML文件,无需手动打开每封邮件
- 结构化汇总:自动提取邮件关键信息,按统一格式整理
- AI友好:生成的纯文本报告可直接作为AI提示词,快速生成年终总结
- 编码兼容:完美解决中文邮件、中文路径乱码问题
二、环境准备
1. 安装Python
确保本地安装Python 3.7及以上版本(推荐3.9+),可从Python官网下载安装。
2. 安装依赖库
打开命令提示符(CMD)或终端,执行以下命令安装所需依赖:
pip install html2text pywin32 html2text:将邮件中的HTML格式正文转为纯文本pywin32:解决Windows系统中文路径访问问题
三、完整代码实现
将以下代码保存为eml_summary.py文件:
import email import quopri import base64 import html2text from email.header import decode_header import os import glob from datetime import datetime import sys # 解决中文路径问题if sys.platform =='win32':import win32api import win32con defdecode_email_header(header_value):"""解码邮件头(处理中文等非ASCII字符)"""ifnot header_value:return"" decoded_parts = decode_header(header_value) header_parts =[]for part, encoding in decoded_parts:ifisinstance(part,bytes):if encoding: header_parts.append(part.decode(encoding, errors='replace'))else:# 尝试常见编码try: header_parts.append(part.decode('utf-8'))except:try: header_parts.append(part.decode('gbk'))except: header_parts.append(part.decode('latin-1'))else: header_parts.append(part)return''.join(header_parts)defdecode_base64_content(content, charset='utf-8'):"""专门解码base64编码的邮件正文"""try:# 先解码base64 decoded_bytes = base64.b64decode(content)# 再解码字符集return decoded_bytes.decode(charset, errors='replace')except Exception as e:try:return decoded_bytes.decode('gbk', errors='replace')except:return decoded_bytes.decode('latin-1', errors='replace')defdecode_email_body(part):"""解码邮件正文内容(增强版)"""# 获取原始payload payload = part.get_payload(decode=False) charset = part.get_content_charset()or'utf-8'# 处理不同的传输编码 transfer_encoding = part.get('Content-Transfer-Encoding','').lower()if transfer_encoding =='base64':# 专门处理base64编码 text = decode_base64_content(payload, charset)elif transfer_encoding =='quoted-printable':# 处理quoted-printable编码 decoded_bytes = quopri.decodestring(payload)try: text = decoded_bytes.decode(charset, errors='replace')except: text = decoded_bytes.decode('gbk', errors='replace')else:# 普通编码try: text = payload.decode(charset, errors='replace')except:try: text = payload.decode('gbk', errors='replace')except: text = payload.decode('latin-1', errors='replace')return text defextract_email_content(eml_file_path):"""解析单个EML文件(修复中文路径和编码问题)"""try:# 处理Windows中文路径问题if sys.platform =='win32': eml_file_path = win32api.GetShortPathName(eml_file_path)# 读取EML文件(使用rb模式避免编码问题)withopen(eml_file_path,'rb')as f: msg = email.message_from_bytes(f.read())# 提取邮件基本信息 email_info ={'文件名': os.path.basename(eml_file_path),'发件人': decode_email_header(msg.get('From','')),'收件人': decode_email_header(msg.get('To','')),'抄送': decode_email_header(msg.get('Cc','')),'主题': decode_email_header(msg.get('Subject','')),'邮件日期': decode_email_header(msg.get('Date','')),'正文':'','解析状态':'成功'}# 提取正文内容 body_text ="" body_html =""# 遍历邮件部分if msg.is_multipart():for part in msg.walk(): content_type = part.get_content_type() content_disposition =str(part.get("Content-Disposition"))# 跳过附件if"attachment"in content_disposition:continue# 提取纯文本内容if content_type =="text/plain": body_text = decode_email_body(part)# 提取HTML内容(后续转为文本)elif content_type =="text/html": body_html = decode_email_body(part)else:# 非多部分邮件 content_type = msg.get_content_type()if content_type =="text/plain": body_text = decode_email_body(msg)elif content_type =="text/html": body_html = decode_email_body(msg)# 优先使用纯文本,若无则将HTML转为文本if body_text: email_info['正文']= body_text elif body_html:# 将HTML转为纯文本(优化配置) h2t = html2text.HTML2Text() h2t.ignore_links =False h2t.ignore_images =True h2t.unicode_snob =True h2t.body_width =0 email_info['正文']= h2t.handle(body_html)except Exception as e:# 详细记录错误信息 error_msg =f'失败:{str(e)}' email_info ={'文件名': os.path.basename(eml_file_path),'解析状态': error_msg,'发件人':'','收件人':'','抄送':'','主题':'','邮件日期':'','正文':''}print(f"解析 {os.path.basename(eml_file_path)} 出错:{error_msg}")return email_info defsave_summary_to_txt(email_info_list, output_file_path):"""将所有解析后的邮件内容汇总保存为TXT文件"""# 确保输出目录存在 output_dir = os.path.dirname(output_file_path)if output_dir andnot os.path.exists(output_dir): os.makedirs(output_dir)withopen(output_file_path,'w', encoding='utf-8', errors='replace')as f:# 写入汇总标题 f.write("="*80+"\n") f.write(f"EML文件批量解析汇总报告\n") f.write(f"汇总时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") f.write(f"解析文件总数:{len(email_info_list)}\n") f.write(f"成功解析数:{len([x for x in email_info_list if x['解析状态']=='成功'])}\n") f.write(f"失败解析数:{len([x for x in email_info_list if x['解析状态']!='成功'])}\n") f.write("="*80+"\n\n")# 遍历每个邮件的解析结果for idx, email_info inenumerate(email_info_list,1): f.write(f"【第{idx}个文件】\n") f.write("-"*60+"\n")# 写入该邮件的所有信息for key, value in email_info.items():if value:# 只写入非空内容if key =='正文': f.write(f"{key}:\n{value}\n\n")else: f.write(f"{key}:{value}\n")# 每个文件之间的分隔符 f.write("\n"+"="*80+"\n\n")defmain():# 配置输出文件路径 output_txt ="EML文件汇总解析结果.txt"# 获取当前文件夹下所有.eml文件(处理中文路径) current_dir = os.getcwd() eml_files =[]forfilein os.listdir(current_dir):iffile.lower().endswith('.eml'): eml_files.append(os.path.join(current_dir,file))# 检查是否找到EML文件ifnot eml_files:print("错误:当前文件夹下未找到任何.eml文件")returnprint(f"找到 {len(eml_files)} 个.eml文件,开始批量解析...")print("-"*50)# 批量解析每个EML文件 email_info_list =[]for eml_file in eml_files:print(f"正在解析:{os.path.basename(eml_file)}") email_content = extract_email_content(eml_file) email_info_list.append(email_content)# 打印解析状态 status ="✅ 成功"if email_content['解析状态']=='成功'else"❌ 失败"print(f"状态:{status}")# 保存汇总结果print("\n正在保存汇总结果...") save_summary_to_txt(email_info_list, output_txt)# 输出汇总信息print("-"*50)print(f"批量解析完成!")print(f"汇总结果已保存至:{os.path.abspath(output_txt)}")print(f"📊 汇总统计:")print(f" 总文件数:{len(eml_files)}") success_count =len([x for x in email_info_list if x['解析状态']=='成功']) fail_count =len([x for x in email_info_list if x['解析状态']!='成功'])print(f" 成功解析:{success_count}")print(f" 失败解析:{fail_count}")# 输出失败的文件列表(如果有) failed_files =[x['文件名']for x in email_info_list if x['解析状态']!='成功']if failed_files:print(f"\n❌ 解析失败的文件:")forfilein failed_files[:10]:# 只显示前10个print(f" - {file}")iflen(failed_files)>10:print(f" - ... 还有 {len(failed_files)-10} 个文件解析失败")if __name__ =="__main__":# 设置系统编码if sys.platform =='win32': os.system('chcp 65001 > nul')# 设置控制台编码为UTF-8# 安装依赖(首次运行时取消注释执行)# os.system("pip install html2text pywin32") main()四、使用步骤
1. 整理EML文件
将需要解析的所有EML格式邮件文件,复制到eml_summary.py脚本所在的文件夹中。
2. 运行脚本
- Windows系统:双击
eml_summary.py文件,或在脚本所在文件夹按住Shift+右键,选择“在此处打开命令窗口”,执行python eml_summary.py - Mac/Linux系统:打开终端,切换到脚本所在目录,执行
python3 eml_summary.py
3. 查看解析结果
脚本运行完成后,会在同一目录生成EML文件汇总解析结果.txt文件,包含:
- 汇总统计(总文件数、成功/失败数)
- 每封邮件的完整信息(文件名、发件人、收件人、主题、日期、正文)
- 错误提示(解析失败的文件及原因)
五、核心功能解析
1. 编码处理
decode_email_header:解码邮件头中的中文内容,自动适配UTF-8、GBK等编码decode_email_body:处理Base64、Quoted-Printable等编码格式的邮件正文- 解决Windows中文路径访问问题,避免文件读取失败
2. 内容提取
- 自动区分纯文本/HTML格式正文,HTML正文自动转为纯文本
- 跳过邮件附件,只提取核心文本内容
- 完整提取发件人、收件人、抄送、主题、日期等关键信息
3. 结果汇总
- 生成结构化的TXT报告,便于阅读和AI处理
- 详细的解析状态统计,方便排查问题
六、AI生成年终总结技巧
将生成的EML文件汇总解析结果.txt内容复制,作为提示词投喂给AI(如ChatGPT、文心一言、讯飞星火等),示例提示词:
请基于以下邮件记录,帮我生成一份2024年度工作总结,要求: 1. 总结工作成果和完成的项目 2. 分析工作中的亮点和不足 3. 提出2025年的工作计划和改进方向 4. 语言正式、逻辑清晰,分点阐述,字数约1500字 【邮件记录开始】 [粘贴TXT文件中的所有内容] 【邮件记录结束】 AI提示词优化建议:
- 指定角色:“以XX岗位的身份”、“站在团队负责人的角度”
- 明确结构:“分为工作成果、问题反思、未来规划三部分”
- 突出重点:“重点体现项目推进、客户沟通、跨部门协作的工作内容”
- 调整风格:“语言简洁干练”、“突出数据和成果”
七、常见问题解决
1. 脚本运行提示缺少模块
执行pip install 缺失的模块名,如pip install html2text
2. 中文乱码
- 确保脚本文件编码为UTF-8
- Windows系统已自动设置控制台编码为UTF-8(脚本内置处理)
- 生成的TXT文件用Notepad++等编辑器打开,选择UTF-8编码
3. 部分邮件解析失败
- 检查EML文件是否损坏
- 特殊格式的邮件(如加密、特殊编码)可能解析失败,可手动打开查看
- 查看控制台的错误提示,针对性处理
八、扩展优化建议
- 按时间筛选:增加邮件日期筛选功能,只解析指定时间段的邮件
- 关键词提取:集成jieba分词,自动提取邮件中的核心关键词
- Excel导出:将结果导出为Excel格式,便于数据筛选和分析
- 分类汇总:按发件人/主题/项目自动分类邮件内容
- 批量导出附件:增加附件提取功能,汇总邮件中的附件文件
总结
本教程提供的EML邮件批量解析脚本,能快速将分散的邮件记录转化为结构化的文本报告,结合AI工具可大幅提升年终总结的撰写效率。不仅适用于年终总结,还可用于项目复盘、工作汇报、客户沟通记录整理等场景,是职场高效办公的实用工具。
通过简单的脚本调整,还能适配更多个性化需求,建议根据自己的工作场景优化使用,让数据整理和总结撰写更高效!