Konwersja EML i MSG

Konwersja EML i MSG

Aspose.Email FOSS dla C++ konwertuje dwukierunkowo pomiędzy EML (RFC 5322 / MIME) oraz MSG formatami (Outlook MAPI) przy użyciu mapi_message. Ścieżka konwersji to: load_from_eml() → w pamięci mapi_messagesave() dla EML→MSG, oraz from_file() / from_stream()save_to_eml() dla MSG→EML.


Konwertuj EML do MSG

Wczytaj plik EML za pomocą mapi_message::load_from_eml(), a następnie serializuj do MSG przy użyciu 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() analizuje strukturę MIME i wypełnia temat MAPI, treść w formacie tekstu zwykłego, treść HTML, tożsamość nadawcy, listę odbiorców oraz wszystkie części załączników.


Konwertuj MSG do EML

Wczytaj plik MSG za pomocą mapi_message::from_file(), a następnie wywołaj 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";
}

Konwersja oparta na strumieniach

Wszystkie cztery istotne metody akceptują przeciążenia std::istream / std::ostream umożliwiające przetwarzanie w stylu potoku bez ingerencji w system plików:

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

Zawsze otwieraj strumienie przy użyciu std::ios::binary. Strumienie w trybie tekstowym tłumaczą znaki końca linii w systemie Windows, uszkadzając binarne dane CFB.


Konwersja w pamięci (bajty)

save() i save_to_eml() posiadają oba przeciążenia bezargumentowe zwracające std::vector<std::uint8_t>. Użyj ich, aby uniknąć wszelkiego wejścia/wyjścia z systemem plików:

#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...
}

Konwersja wsadowa katalogu

Iteruj katalog przy użyciu std::filesystem::directory_iterator, aby w jednym przebiegu przekonwertować wszystkie pliki .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';
    }
}

Wskazówki i najlepsze praktyki

  • Otwieraj wszystkie strumienie plików przy użyciu std::ios::binary — zarówno wejścia, jak i wyjścia.
  • Preferuj load_from_eml(path) zamiast przeciążenia strumienia, gdy masz ścieżkę; przeciążenie ścieżki otwiera plik wewnętrznie i jest nieco prostsze.
  • Używaj przeciążeń bajtowych (save() i save_to_eml() bez argumentów) przy przekazywaniu danych między usługami, aby uniknąć plików tymczasowych.
  • Temat, treść, HTML treść, nadawca, odbiorcy oraz załączniki MIME są zachowywane w pełnym cyklu.
  • Flagi IMAP, nagłówki routingu i zawartość zakodowana w TNEF nie są przenoszone podczas konwersji.

Typowe problemy

ProblemPrzyczynaNaprawa
load_from_eml wyrzuca błąd przy prawidłowym plikuKońcówki linii nie-CRLF w EMLUpewnij się, że EML używa CRLF zgodnie z RFC5322; niektóre narzędzia eksportujące zapisują jedynie LF
Brakujące załączniki po EML → MSGNiestandardowe kodowanie załącznika MIMEZweryfikuj, czy EML używa multipart/mixed ze standardowym Content-Disposition: attachment
Puste ciało HTML po MSG → EMLŹródłowy MSG ma tylko ciało tekstoweSprawdź message.html_body(); jeśli jest pusty, zapisano tylko tekst zwykły
Wyjście strumienia jest uszkodzoneStrumień został otwarty w trybie tekstowymZawsze używaj std::ios::binary
Temat zawiera sekwencje ?=Zakodowane słowo RFC 2047 w oryginalnym EMLDekoduj przy użyciu biblioteki RFC 2047; biblioteka zachowuje zakodowaną formę

FAQ

Czy EML → MSG zachowuje HTML treść?

Tak. Część MIME text/html jest przechowywana w właściwości ciała MAPI HTML i jest dostępna przez message.html_body() po załadowaniu.

Czy załączniki są zachowywane w obu kierunkach?

Tak. Wszystkie części załączników MIME są przenoszone przez listę załączników mapi_message. Binarny zestaw danych załącznika jest dostępny jako attachment.data (a std::vector<std::uint8_t>).

Czy mogę konwertować pojedynczy plik EML na wiele formatów wyjściowych jednocześnie?

Tak. Załaduj plik EML raz przy użyciu load_from_eml(), a następnie wywołaj zarówno save(), jak i save_to_eml() na tym samym obiekcie mapi_message w pamięci.

Czy load_from_eml() jest bezpieczny wątkowo?

Każde wywołanie tworzy niezależną instancję mapi_message. Wiele wątków może wywoływać load_from_eml() jednocześnie, pod warunkiem że każdy wątek używa własnego obiektu wyjściowego.

Co się dzieje z wiadomościami, które nie mają treści w formacie zwykłego tekstu?

Jeśli EML zawiera tylko część text/html, message.body() zwraca pusty ciąg znaków, a message.html_body() przenosi zawartość HTML. Oba są zachowywane przy serializacji MSG.


API Reference Podsumowanie

Klasa / MetodaOpis
mapi_message::load_from_eml(path)Przetwórz plik EML na mapi_message
mapi_message::load_from_eml(stream)Przetwórz EML z std::istream
mapi_message::save(path)Serializuj mapi_message do pliku MSG
mapi_message::save(stream)Zapisz bajty MSG do std::ostream
mapi_message::save()Zwróć MSG jako std::vector<std::uint8_t>
mapi_message::from_file(path)Wczytaj plik MSG do mapi_message
mapi_message::from_stream(stream)Wczytaj MSG z std::istream
mapi_message::save_to_eml(path)Zapisz EML do ścieżki pliku
mapi_message::save_to_eml(stream)Zapisz bajty EML do std::ostream
mapi_message::save_to_eml()Zwróć EML jako std::vector<std::uint8_t>

Zobacz także

 Polski