如何在 C++ 中读取 MSG 文件

如何在 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.git
add_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 文件中的轻微结构偏差。

另请参阅

 中文