如何用C语言将Outlook内嵌MSG附件转为可用MSG对象?
内嵌MSG附件转为合法MSG对象的C语言实现方案
核心逻辑
内嵌MSG附件是MAPI对象实例,无法通过二进制流直接解析,必须借助MAPI的对象接口来获取和操作。
操作步骤
- 验证附件类型:先读取附件的
PR_ATTACH_METHOD属性,确认其值为ATTACH_EMBEDDED_MSG(数值5),确保目标附件是内嵌MSG类型。 - 通过
PR_ATTACH_DATA_OBJ获取MAPI对象:- 调用
HrGetOneProp从附件的MAPIPROP对象中获取PR_ATTACH_DATA_OBJ属性,该属性返回LPMAPIOBJECT指针。 - 对
LPMAPIOBJECT调用OpenEntry,指定接口ID为IID_IMessage,获取LPMESSAGE对象——这就是对应的内嵌MSG邮件对象。 - 操作完成后,必须调用
Release释放所有MAPI对象,避免内存泄漏。
- 调用
- 关于
PR_ATTACH_SIZE的说明:该属性记录的是附件MAPI属性的存储大小,并非导出为MSG文件后的实际文件大小,因此数值偏小属于正常现象,不能用于判断文件完整性。 - 导出为标准MSG文件(可选):若需将获取到的
LPMESSAGE保存为本地MSG文件,可调用IMessage::SaveChanges(配合MAPI_DEFERRED_ERRORS参数),再通过HrExportMessage函数完成导出。
关键代码示例
// 假设已获取到附件的MAPIPROP对象pAttachProp LPMAPIOBJECT pEmbeddedObj = NULL; LPMESSAGE pEmbeddedMsg = NULL; SPropValue* pPropVal = NULL; // 获取PR_ATTACH_DATA_OBJ属性 HRESULT hr = HrGetOneProp(pAttachProp, PR_ATTACH_DATA_OBJ, &pPropVal); if (SUCCEEDED(hr) && pPropVal->Value.lpMAPIOBJECT) { pEmbeddedObj = pPropVal->Value.lpMAPIOBJECT; pEmbeddedObj->AddRef(); // 增加引用计数 // 打开内嵌邮件对象 hr = pEmbeddedObj->OpenEntry(0, NULL, &IID_IMessage, MAPI_BEST_ACCESS, NULL, (LPUNKNOWN*)&pEmbeddedMsg); if (SUCCEEDED(hr)) { // 此处可对pEmbeddedMsg进行属性读取、内容操作等处理 // ... 业务逻辑代码 ... pEmbeddedMsg->Release(); } pEmbeddedObj->Release(); } // 释放属性缓冲区 if (pPropVal) { MAPIFreeBuffer(pPropVal); }
注意事项
- 程序初始化阶段需调用
MAPIInitialize,退出时调用MAPIUninitialize,确保MAPI环境正常。 - 排查错误时,使用
MAPIError函数获取详细错误信息,定位问题更高效。 - 严格遵循COM对象引用计数规则,所有MAPI对象使用后必须调用
Release,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Mircea
相关产品推荐
相关产品推荐

