تبدیل 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() بارگذاری کنید، سپس با save() به MSG سریالسازی کنید:
#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، بدنه متن ساده، بدنه 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 باز کنید. جریانهای حالت متنی انتهای خطها را در ویندوز ترجمه میکنند و دادههای باینری 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باز کنید — هم برای ورودی و هم برای خروجی. - در صورتی که مسیر دارید، به جای overload جریان،
load_from_eml(path)را ترجیح دهید؛ overload مسیر باز کردن فایل را بهصورت داخلی مدیریت میکند و کمی سادهتر است. - از overloadهای بایت (
save()وsave_to_eml()بدون آرگومان) زمانی که دادهها را بین سرویسها لولهکشی میکنید، استفاده کنید تا از فایلهای موقت جلوگیری شود. - موضوع، متن، متن HTML، فرستنده، دریافتکنندگان و پیوستهای MIME همگی در طول مسیر کامل حفظ میشوند.
- پرچمهای IMAP، هدرهای مسیریابی و محتوای رمزگذاریشده بهصورت TNEF در تبدیل منتقل نمیشوند.
مسائل رایج
| مسئله | دلیل | اصلاح |
|---|---|---|
load_from_eml در یک فایل معتبر خطا میدهد | پایان خطوط غیر CRLF در EML | اطمینان حاصل کنید که EML از CRLF مطابق RFC 5322 استفاده میکند؛ برخی ابزارهای خروجی فقط LF مینویسند |
| پیوستهای گمشده پس از تبدیل EML → MSG | رمزگذاری پیوست MIME غیر استاندارد | تأیید کنید که EML از multipart/mixed با Content-Disposition: attachment استاندارد استفاده میکند |
| بدنهٔ خالی HTML پس از MSG → EML | منبع MSG فقط دارای بدنهٔ متن ساده است | بررسی کنید message.html_body()؛ اگر خالی باشد، فقط متن ساده ذخیره شده است |
| خروجی استریم خراب است | جریان در حالت متنی باز شد | همیشه از std::ios::binary استفاده کنید |
موضوع توالیهای ?= را نشان میدهد | کلمهکدگذاری شده RFC 2047 در EML اصلی | با یک کتابخانه RFC 2047 رمزگشایی کنید؛ کتابخانه فرم رمزگذاریشده را حفظ میکند |
FAQ
آیا تبدیل EML → MSG متن HTML را حفظ میکند؟
بله. یک بخش MIME text/html در ویژگی بدنه 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() را صدا بزنند به شرطی که هر رشته از شیء خروجی خود استفاده کند.
چه اتفاقی برای پیامهایی که بدنه متن ساده ندارند میافتد؟
اگر 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> |