如何使用Python将PST文件转换为EML格式并保留格式与附件?
Python将PST文件转换为EML格式的实现方案
要实现PST转EML并保留格式与附件,目前有两种可靠的方案,分别适配不同环境:
方法一:使用pywin32调用Outlook COM接口(Windows环境推荐)
该方案依赖Outlook客户端的原生解析能力,能100%保留邮件的HTML格式、附件、收件人/发件人等完整信息,是最稳定的选择。
操作步骤
- 确保Windows系统已安装Outlook客户端
- 安装依赖库:
pip install pywin32
代码示例
import win32com.client import os def pst_to_eml(pst_path, output_dir): # 初始化Outlook MAPI命名空间 outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") # 加载目标PST文件 outlook.AddStore(pst_path) # 定位PST根文件夹 pst_root = None for store in outlook.Stores: if store.FilePath == pst_path: pst_root = store.GetRootFolder() break if not pst_root: print("无法找到目标PST文件的根文件夹") return # 递归遍历所有邮件文件夹 def traverse_folder(folder): for item in folder.Items: # 仅处理邮件类型项(Class=43对应MailItem) if item.Class == 43: # 处理邮件主题中的非法文件名字符 safe_subject = item.Subject.replace('/', '_').replace('\\', '_').replace(':', '_') eml_path = os.path.join(output_dir, f"{safe_subject}.eml") # 保存为EML格式(4对应olMSGUnicode格式,实际输出标准EML) item.SaveAs(eml_path, 4) # 遍历子文件夹 for subfolder in folder.Folders: traverse_folder(subfolder) # 创建输出目录 os.makedirs(output_dir, exist_ok=True) traverse_folder(pst_root) # 移除加载的PST文件(可选) outlook.RemoveStore(pst_root) # 使用示例 pst_to_eml("C:/Example/input.pst", "C:/Example/output_emls")
说明
- 首次运行可能触发Outlook安全提示,需手动允许程序访问邮件数据
- 自动保留所有附件、内嵌图片和HTML格式
- 支持遍历PST内的所有子文件夹
方法二:使用libpff的Python绑定(跨平台)
libpff是开源的PST解析库,支持Linux、macOS等跨平台环境,但对复杂HTML格式和附件的处理能力略逊于Outlook原生方案。
操作步骤
- 安装libpff依赖(Linux可通过包管理器安装,Windows需下载预编译版本)
- 安装Python绑定:
pip install pypff
代码示例
import pypff import os def pst_to_eml_libpff(pst_path, output_dir): pst = pypff.file() pst.open(pst_path) root_folder = pst.get_root_folder() # 递归遍历文件夹 def traverse_folder(folder): for msg in folder.sub_messages: try: # 获取邮件原始字节流 msg_data = msg.get_internet_message_stream() # 处理非法文件名 safe_subject = msg.subject.replace('/', '_').replace('\\', '_').replace(':', '_') if msg.subject else "无主题邮件" eml_path = os.path.join(output_dir, f"{safe_subject}.eml") # 写入EML文件 with open(eml_path, 'wb') as f: f.write(msg_data) # 单独提取附件(可选) for att in msg.attachments: att_path = os.path.join(output_dir, f"{safe_subject}_附件_{att.filename}") with open(att_path, 'wb') as f: f.write(att.read_buffer()) except Exception as e: print(f"处理邮件失败:{str(e)}") # 遍历子文件夹 for subfolder in folder.sub_folders: traverse_folder(subfolder) os.makedirs(output_dir, exist_ok=True) traverse_folder(root_folder) pst.close() # 使用示例 pst_to_eml_libpff("/home/example/input.pst", "/home/example/output_emls")
说明
- 跨平台无需Outlook,但对部分复杂HTML邮件的格式还原可能不完整
- 附件需单独提取保存,可根据需求调整逻辑
注意事项
- 格式保留优先级:优先选择pywin32方案,原生Outlook处理能完美还原所有格式细节
- 性能:大体积PST文件建议分批次处理,避免内存占用过高
- 权限:使用pywin32时,需确保Outlook信任该程序的访问权限
内容的提问来源于stack exchange,提问作者NobodyKnowsAboutMe
相关产品推荐
相关产品推荐

