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_message → save() 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()isave_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
| Problem | Przyczyna | Naprawa |
|---|---|---|
load_from_eml wyrzuca błąd przy prawidłowym pliku | Końcówki linii nie-CRLF w EML | Upewnij się, że EML używa CRLF zgodnie z RFC5322; niektóre narzędzia eksportujące zapisują jedynie LF |
| Brakujące załączniki po EML → MSG | Niestandardowe kodowanie załącznika MIME | Zweryfikuj, 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 tekstowe | Sprawdź message.html_body(); jeśli jest pusty, zapisano tylko tekst zwykły |
| Wyjście strumienia jest uszkodzone | Strumień został otwarty w trybie tekstowym | Zawsze używaj std::ios::binary |
Temat zawiera sekwencje ?= | Zakodowane słowo RFC 2047 w oryginalnym EML | Dekoduj 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 / Metoda | Opis |
|---|---|
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> |