Конвертація EML та MSG
Конвертація EML і MSG
Aspose.Email FOSS для C++ виконує двостороннє перетворення між EML (RFC 5322 / MIME) і MSG (Outlook MAPI) форматами за допомогою mapi_message. Шлях перетворення: load_from_eml() → у пам’яті mapi_message → save() для EML→MSG, і from_file() / from_stream() → save_to_eml() для MSG→EML.
Перетворити EML у MSG
Завантажте файл EML за допомогою mapi_message::load_from_eml(), потім серіалізуйте у MSG за допомогою save():
#include <filesystem>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
const auto message = aspose::email::foss::msg::mapi_message::load_from_eml(
std::filesystem::path("message.eml"));
std::cout << "Subject: " << message.subject() << '\n';
message.save(std::filesystem::path("converted.msg"));
std::cout << "Saved converted.msg\n";
}load_from_eml() аналізує структуру MIME і заповнює тему MAPI, тіло у форматі plain-text, тіло HTML, особу відправника, список одержувачів та всі частини вкладень.
Перетворити MSG у EML
Завантажте файл MSG за допомогою mapi_message::from_file(), потім викличте save_to_eml():
#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"));
message.save_to_eml(std::filesystem::path("exported.eml"));
std::cout << "Saved exported.eml\n";
}Конверсія на основі потоків
Усі чотири відповідні методи приймають перевантаження std::istream / std::ostream для обробки у стилі конвеєра без доступу до файлової системи:
#include <fstream>
#include <filesystem>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
// EML → MSG via streams
std::ifstream eml_in("message.eml", std::ios::binary);
const auto message = aspose::email::foss::msg::mapi_message::load_from_eml(eml_in);
std::ofstream msg_out("converted.msg", std::ios::binary);
message.save(msg_out);
// MSG → EML via streams
std::ifstream msg_in("converted.msg", std::ios::binary);
const auto reloaded = aspose::email::foss::msg::mapi_message::from_stream(msg_in);
std::ofstream eml_out("roundtrip.eml", std::ios::binary);
reloaded.save_to_eml(eml_out);
}Завжди відкривайте потоки за допомогою std::ios::binary. Потоки у текстовому режимі переводять закінчення рядків у Windows, пошкоджуючи бінарні дані CFB.
Конверсія в пам’яті (байти)
save() і save_to_eml() мають перевантаження без аргументів, які повертають std::vector<std::uint8_t>. Використовуйте їх, щоб уникнути будь-якого вводу/виводу файлової системи:
#include <filesystem>
#include <vector>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
const auto message = aspose::email::foss::msg::mapi_message::load_from_eml(
std::filesystem::path("message.eml"));
const std::vector<std::uint8_t> msg_bytes = message.save();
const std::vector<std::uint8_t> eml_bytes = message.save_to_eml();
// Write to a database, network socket, or other destination...
}Пакетна конверсія каталогів
Пройдіться по каталогу за допомогою std::filesystem::directory_iterator, щоб конвертувати всі файли .eml за один прохід:
#include <filesystem>
#include <iostream>
#include "aspose/email/foss/msg/mapi_message.hpp"
int main()
{
const std::filesystem::path input_dir("emails/eml");
const std::filesystem::path output_dir("emails/msg");
std::filesystem::create_directories(output_dir);
for (const auto& entry : std::filesystem::directory_iterator(input_dir))
{
if (entry.path().extension() != ".eml")
continue;
const auto message = aspose::email::foss::msg::mapi_message::load_from_eml(
entry.path());
auto out_path = output_dir / entry.path().filename();
out_path.replace_extension(".msg");
message.save(out_path);
std::cout << "Converted: " << entry.path().filename() << '\n';
}
}Поради та найкращі практики
- Відкривайте всі файлові потоки за допомогою
std::ios::binary— і вхідні, і вихідні. - Віддавайте перевагу
load_from_eml(path)над перевантаженням потоку, коли у вас є шлях; перевантаження за шляхом обробляє відкриття файлу внутрішньо і трохи простіше. - Використовуйте байтові перевантаження (
save()іsave_to_eml()без аргументів), коли передаєте дані між сервісами, щоб уникнути тимчасових файлів. - Тема, тіло листа, HTML тіло, відправник, отримувачі та MIME-вкладення зберігаються протягом усього циклу.
- IMAP-позначки, заголовки маршрутизації та TNEF-зашифрований вміст не переносяться під час конвертації.
Типові проблеми
| Проблема | Причина | Виправлення |
|---|---|---|
load_from_eml викидає виключення на дійсному файлі | Неправильні закінчення рядків (не CRLF) у EML | Переконайтеся, що EML використовує CRLF згідно RFC5322; деякі інструменти експорту записують лише LF |
| Відсутні вкладення після EML → MSG | Нестандартне кодування MIME-вкладень | Перевірте, що EML використовує multipart/mixed зі стандартним Content-Disposition: attachment |
| Порожнє тіло HTML після MSG → EML | Вихідний MSG має лише простий текст у тілі | Перевірте message.html_body(); якщо порожньо, збережено лише простий текст |
| Потік виводу пошкоджений | Потік відкрито у текстовому режимі | Завжди використовуйте std::ios::binary |
Тема містить послідовності ?= | Закодоване слово RFC 2047 у оригінальному EML | Декодуйте за допомогою бібліотеки RFC2047; бібліотека зберігає закодовану форму |
FAQ
Чи зберігає EML → MSG HTML тіло?
Так. Частина text/html MIME зберігається у властивості тіла MAPI HTML і доступна через message.html_body() після завантаження.
Чи зберігаються вкладення в обох напрямках?
Так. Усі частини вкладень MIME передаються через список вкладень mapi_message. Двійкові дані вкладення доступні як attachment.data (це std::vector<std::uint8_t>).
Чи можу я одночасно конвертувати один файл EML у кілька форматів виводу?
Так. Завантажте EML один раз за допомогою load_from_eml(), потім викличте і save(), і save_to_eml() на тому ж об’єкті mapi_message у пам’яті.
Чи є load_from_eml() потоково-безпечним?
Кожний виклик створює незалежний екземпляр mapi_message. Кілька потоків можуть одночасно викликати load_from_eml(), за умови, що кожен потік використовує власний об’єкт виводу.
Що відбувається з повідомленнями, у яких відсутнє plain-text тіло?
Якщо EML містить лише частину text/html, message.body() повертає порожній рядок, а message.html_body() несе вміст HTML. Обидва зберігаються під час серіалізації MSG.
API Reference Підсумок
| Клас / Метод | Опис |
|---|---|
mapi_message::load_from_eml(path) | Розпарсити файл EML у mapi_message |
mapi_message::load_from_eml(stream) | Розпарсити EML з std::istream |
mapi_message::save(path) | Серіалізувати mapi_message у файл MSG |
mapi_message::save(stream) | Записати байти MSG у std::ostream |
mapi_message::save() | Повернути MSG як std::vector<std::uint8_t> |
mapi_message::from_file(path) | Завантажити файл MSG у mapi_message |
mapi_message::from_stream(stream) | Завантажити MSG з std::istream |
mapi_message::save_to_eml(path) | Записати EML у шлях файлу |
mapi_message::save_to_eml(stream) | Записати байти EML у std::ostream |
mapi_message::save_to_eml() | Повернути EML як std::vector<std::uint8_t> |