Читання файлів MSG

Читання файлів MSG

mapi_message є точкою входу для завантаження та розбору файлів Outlook MSG. Один виклик from_file() або from_stream() читає повний контейнер CFB, витягує всі властивості MAPI і надає їх через типізовані методи доступу — без необхідності встановлення Outlook.


Завантажити з шляхом до файлу

Використовуйте mapi_message::from_file() з std::filesystem::path:

#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';
}

Завантажити з потоку

Використовуйте mapi_message::from_stream(), коли дані MSG надходять з мережевого сокету, архіву або будь-якого std::istream:

#include <fstream>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"

int main()
{
    std::ifstream input("sample.msg", std::ios::binary);
    const auto message = aspose::email::foss::msg::mapi_message::from_stream(input);

    std::cout << "Subject: " << message.subject() << '\n';
}

Завжди відкривайте потік за допомогою std::ios::binary. Потоки у текстовому режимі переводять закінчення рядків у Windows і пошкоджують контейнер CFB.


Доступ до властивостей повідомлення

mapi_message надає найпоширеніші властивості повідомлення у вигляді іменованих геттерів:

#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"));

    // Core properties
    std::cout << "Subject:          " << message.subject() << '\n';
    std::cout << "Sender name:      " << message.sender_name() << '\n';
    std::cout << "Sender email:     " << message.sender_email_address() << '\n';
    std::cout << "Internet msg-id:  " << message.internet_message_id() << '\n';
    std::cout << "Message class:    " << message.message_class() << '\n';

    // Body — check html_body() first; fall back to plain body()
    const auto& body = message.html_body().empty()
        ? message.body()
        : message.html_body();
    std::cout << "Body length: " << body.size() << " chars\n";
}

Перебрати отримувачів

message.recipients() повертає std::vector об’єктів отримувачів з display_name, email_address та recipient_type:

#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"));

    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';
    }
}

Перебрати вкладення

message.attachments() повертає std::vector об’єктів вкладень. Кожен з них надає filename, mime_type, data, content_id та is_embedded_message():

#include <filesystem>
#include <fstream>
#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"));

    for (const auto& a : message.attachments())
    {
        std::cout << a.filename
                  << "  " << a.mime_type
                  << "  " << a.data.size() << " bytes"
                  << "  embedded=" << (a.is_embedded_message() ? "yes" : "no")
                  << '\n';

        if (!a.is_embedded_message())
        {
            std::ofstream out("extracted_" + a.filename, std::ios::binary);
            out.write(reinterpret_cast<const char*>(a.data.data()),
                      static_cast<std::streamsize>(a.data.size()));
        }
    }
}

Доступ до вбудованих повідомлень

Коли is_embedded_message() є true, вкладення містить інший файл MSG. Доступ до нього можна отримати через attachment.embedded_message:

#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"));

    for (const auto& a : message.attachments())
    {
        if (a.is_embedded_message() && a.embedded_message != nullptr)
        {
            const auto& inner = *a.embedded_message;
            std::cout << "Embedded subject: " << inner.subject() << '\n';
            inner.save(std::filesystem::path("embedded.msg"));
        }
    }
}

Поради та кращі практики

  • Завжди передавайте std::ios::binary у std::ifstream під час завантаження файлів MSG.
  • Перевірте html_body() перед body() — HTML-only повідомлення зберігають свій вміст у властивості тіла HTML і залишають body() порожнім.
  • from_file() завантажує всі дані вкладень у пам’ять. Для великих файлів MSG розгляньте можливість відкриття базового контейнера за допомогою msg_reader, щоб переглянути метадані без повного матеріалізування байтів вкладень.
  • Параметр strict у from_file(path, strict) та from_stream(stream, strict) за замовчуванням дорівнює false, допускаючи незначні структурні відхилення у реальних файлах MSG.
  • Об’єкти отримувачів надають recipient_type для розрізнення записів To, Cc та Bcc.

Поширені проблеми

ПроблемаПричинаВиправлення
msg_exception на файлі, що виглядає дійснимФайл не є справжнім контейнером OLE CFBПеревірте за допомогою cfb_reader::from_file() — якщо воно також викидає, файл не є дійсним MSG
body() повертає порожній рядокПовідомлення використовує лише тіло HTMLВикористовуйте html_body() замість
recipients() порожнєСтаріший MSG без таблиці отримувачівОтримайте доступ до display_to через get_property_value() за допомогою common_message_property_id::display_to
Пошкодження потоку у WindowsПотік відкрито без std::ios::binaryДодайте прапорець std::ios::binary до std::ifstream
Високе використання пам’яті для великих файлівУсі дані вкладень завантажуються заздалегідьВикористовуйте msg_reader для низькорівневого доступу без повної матеріалізації

FAQ

Чи from_file() залишає файловий дескриптор відкритим?

Ні. Файл відкривається, повністю аналізується і закривається до того, як метод повертає управління. Після виклику ви можете перемістити або видалити вихідний файл.

Як визначити, чи є вкладення файлом, чи вбудованим MSG?

Викличте attachment.is_embedded_message(). Повертає true для вбудованих MSG-файлів; false для звичайних файлових вкладень. Для вбудованих повідомлень доступ до вкладеного об’єкта здійснюється через attachment.embedded_message.

У чому різниця між from_file() і використанням msg_reader?

mapi_message::from_file() — це високорівневий API — він аналізує повне повідомлення і надає властивості у вигляді типізованих полів. msg_reader — це низькорівневий читач, який дає доступ до сирої структури контейнера CFB і корисний, коли потрібно дослідити розташування повідомлення без парсингу всіх властивостей MAPI.

Чи підтримуються і Unicode, і ANSI MSG-файли?

Так. mapi_message обробляє як Unicode (тип властивості ptyp_string), так і ANSI (ptyp_string8) рядкові властивості. unicode_strings() повертає true для повідомлень, збережених з Unicode-властивостями.


API Reference Огляд

Клас / МетодОпис
mapi_message::from_file(path)Завантажити файл MSG з std::filesystem::path
mapi_message::from_file(path, strict)Завантажити з параметром строгого режиму
mapi_message::from_stream(stream)Завантажити MSG з std::istream
mapi_message::from_stream(stream, strict)Завантажити з потоку з параметром строгого режиму
mapi_message::subject()Повернути рядок теми повідомлення
mapi_message::body()Повернути тіло у форматі plain-text
mapi_message::html_body()Повернути тіло HTML (порожньо, якщо відсутнє)
mapi_message::sender_name()Повернути відображуване ім’я відправника
mapi_message::sender_email_address()Повернути email-адресу відправника
mapi_message::internet_message_id()Повернути заголовок RFC 2822 Message-ID
mapi_message::message_class()Повернути рядок класу повідомлення MAPI
mapi_message::recipients()Повернути список отримувачів
mapi_message::attachments()Повернути список вкладень
mapi_attachment::is_embedded_message()True, якщо вкладення є вбудованим MSG
mapi_message::unicode_strings()True, якщо повідомлення використовує властивості Unicode-рядка

Дивіться також

 Українська