如何在 C++ 中读取 MSG 文件
Aspose.Email FOSS for C++ 让您只需一次函数调用即可打开并解析 Outlook MSG 文件。mapi_message::from_file() 和 mapi_message::from_stream() 将完整的邮件——主题、正文、发件人、收件人和附件——加载到内存对象中,无需 Outlook 或 COM 依赖。
步骤 1 — 设置项目
克隆仓库并将其添加到您的 CMakeLists.txt:
git clone https://github.com/aspose-email-foss/Aspose.Email-FOSS-for-Cpp.gitadd_subdirectory(Aspose.Email-FOSS-for-Cpp)
target_link_libraries(your_target PRIVATE AsposeEmailFoss::AsposeEmailFoss)步骤 2 — 包含头文件
#include "aspose/email/foss/msg/mapi_message.hpp"此单一头文件在 aspose::email::foss::msg 命名空间中提供 mapi_message 以及所有支持类型。
步骤 3 — 从文件路径加载消息
当您拥有 std::filesystem::path 时,请使用 mapi_message::from_file():
#include <filesystem>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
const auto message = aspose::email::foss::msg::mapi_message::from_file(
std::filesystem::path("sample.msg"));
std::cout << "Subject: " << message.subject() << '\n';
std::cout << "From: " << message.sender_name()
<< " <" << message.sender_email_address() << ">\n";
std::cout << "Body: " << message.body() << '\n';
}步骤 4 — 从流加载消息
使用 mapi_message::from_stream() 从任意 std::istream 进行解析 — 对于处理通过网络或内存缓冲区接收的 MSG 数据非常有用:
#include <fstream>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
std::ifstream input("sample.msg", std::ios::binary);
auto message = aspose::email::foss::msg::mapi_message::from_stream(input);
std::cout << "Subject: " << message.subject() << '\n';
}始终使用 std::ios::binary 打开流,以防止 Windows 换行符转换损坏 CFB 容器。
步骤 5 — 遍历收件人
message.recipients() 返回一个 std::vector,其中包含收件人对象,每个对象具有 display_name、email_address 和 recipient_type 字段:
#include <fstream>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
std::ifstream input("sample.msg", std::ios::binary);
auto message = aspose::email::foss::msg::mapi_message::from_stream(input);
for (std::size_t i = 0; i < message.recipients().size(); ++i)
{
const auto& r = message.recipients()[i];
std::cout << "[" << (i + 1) << "] "
<< r.display_name << " <" << r.email_address << ">"
<< " type=" << r.recipient_type << '\n';
}
}步骤 6 — 遍历附件
message.attachments() 返回一个 std::vector,其中包含附件对象。每个附件公开 filename、mime_type、data(原始字节)、content_id,以及 is_embedded_message() 谓词:
#include <fstream>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
std::ifstream input("sample.msg", std::ios::binary);
auto message = aspose::email::foss::msg::mapi_message::from_stream(input);
for (std::size_t i = 0; i < message.attachments().size(); ++i)
{
const auto& a = message.attachments()[i];
std::cout << "[" << (i + 1) << "] "
<< a.filename << " mime=" << a.mime_type
<< " bytes=" << a.data.size()
<< " embedded=" << (a.is_embedded_message() ? "yes" : "no")
<< '\n';
}
}常见问题及解决方案
Empty body() 加载后。 某些消息仅在 HTML body 属性中存储文本。检查 message.html_body() when message.body() 返回空字符串。
流已打开但未 std::ios::binary. 在 Windows 上,文本模式流会转换 CRLF 序列,悄悄损坏二进制 CFB 数据。始终使用 MSG 文件时采用 std::ios::binary.
msg_exception 对看似有效的文件抛出异常。 验证文件是真正的 MSG(OLE 复合文件)。某些导出工具保存的文件可能是纯文本或 MIME,且无法被 mapi_message::from_file().
recipients() 返回空向量。 较旧的 MSG 文件有时会省略收件人表,但会在其中存储显示收件人 display_to MAPI 属性。通过 message.get_property_value() with common_message_property_id::display_to and property_type_code::ptyp_string.
内存中的大附件数据。 mapi_message::from_file() and from_stream() 加载整个消息,包括所有附件字节。对于大文件,请使用以下方式打开底层容器 msg_reader 并在不完全实例化的情况下检查附件流。
常见问题
from_file() 与 from_stream() 有何区别?
两者都会生成相同的 mapi_message 对象。 from_file() 接受一个 std::filesystem::path 并在内部打开文件。 from_stream() 可以从您提供的任意 std::istream 读取——当 MSG 数据已在内存中或通过套接字到达时,这非常有用。
在加载后,from_file()会保持文件打开吗?
不会。文件被打开,完整解析到内存中,然后在 from_file() 返回之前关闭。调用结束后即可立即移动或删除源文件。
我可以在 macOS 或 Linux 上读取 Outlook 创建的 MSG 文件吗?
可以。MSG 格式(OLE 复合文件 + MAPI 属性)跨操作系统可移植。任何版本的 Outlook 生成的 .msg 文件都可以使用 mapi_message::from_file() 打开。
我该如何读取 HTML 正文?
调用 message.html_body()。如果消息仅包含纯文本正文,则返回空字符串。message.body() 返回纯文本正文。
严格模式是默认设置吗?
mapi_message::from_file(path, strict) 和 from_stream(stream, strict) 接受一个可选的 strict 布尔值。默认是 false,它容忍实际 MSG 文件中的轻微结构偏差。