Конвертація EML та MSG

Конвертація EML і MSG

Aspose.Email FOSS для C++ виконує двостороннє перетворення між EML (RFC 5322 / MIME) і MSG (Outlook MAPI) форматами за допомогою mapi_message. Шлях перетворення: load_from_eml() → у пам’яті mapi_messagesave() для 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>

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

 Українська