Читання файлів 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-рядка |