Вступ

Програмний розбір електронних листів є поширеною вимогою для інструментів архівації, конвейерів відповідності та утиліт міграції. Файли Outlook MSG використовують контейнерний формат Compound File Binary (CFB) з потоками властивостей MAPI, тоді як файли EML дотримуються стандарту MIME. Обидва формати вимагають ретельного оброблення кодувань, складених заголовків та вкладених вкладень.

Aspose.Email FOSS для .NET — це безкоштовна бібліотека з ліцензією MIT C#, яка забезпечує повний читання-запис API для повідомлень MSG та EML. Вона орієнтована на .NET 8.0+ і не має залежностей від Microsoft Outlook або будь-якого рідного шару COM-інтероп. Бібліотека доступна як пакет aspose.email.foss NuGet.

У цьому дописі розглядаються можливості розбору повідомлень, включені в бібліотеку, від завантаження файлів з диска до видобутку окремих властивостей MAPI та конвертації між форматами.


Що включено

Завантаження файлів MSG

Клас MapiMessage є основною точкою входу для роботи з файлами Outlook MSG. Ви можете завантажити повідомлення за шляхом до файлу або зі стріму, з необов’язковим прапором strict-validation, який виявляє будь-які структурні проблеми у файлі.

// Load an MSG file from disk
var message = MapiMessage.FromFile("meeting-invite.msg");

Console.WriteLine($"Subject: {message.Subject}");
Console.WriteLine($"From: {message.SenderName} <{message.SenderEmailAddress}>");
Console.WriteLine($"Date: {message.MessageDeliveryTime}");
Console.WriteLine($"Recipients: {message.Recipients.Count}");
Console.WriteLine($"Attachments: {message.Attachments.Count}");

Повернутий MapiMessage надає типізовані властивості для загальних полів, включаючи Subject, Body, HtmlBody, SenderName, SenderEmailAddress, InternetMessageId та MessageDeliveryTime.

Завантаження повідомлень EML

Файли EML використовують формат MIME. MapiMessage.LoadFromEml приймає шлях до файлу, Stream або byte[] і повертає той самий об’єкт MapiMessage, тому ви використовуєте єдиний API незалежно від формату джерела.

// Load from a file path
var fromFile = MapiMessage.LoadFromEml("newsletter.eml");

// Load from a stream
using var stream = File.OpenRead("newsletter.eml");
var fromStream = MapiMessage.LoadFromEml(stream);

Console.WriteLine($"Subject: {fromStream.Subject}");
Console.WriteLine($"Body: {fromStream.Body?.Trim()}");

Парсер обробляє складені заголовки, кодування Base64 та quoted-printable, а також поля To/Cc для кількох одержувачів.

Робота з одержувачами та вкладеннями

Після завантаження повідомлення одержувачі та вкладення доступні як строго типізовані колекції. Кожен MapiRecipient містить поля EmailAddress, DisplayName та RecipientType. Кожен MapiAttachment надає Filename, Data, MimeType та ContentId.

var message = MapiMessage.FromFile("report.msg");

foreach (var recipient in message.Recipients)
{
    Console.WriteLine($"  {recipient.DisplayName} <{recipient.EmailAddress}> (type={recipient.RecipientType})");
}

foreach (var attachment in message.Attachments)
{
    Console.WriteLine($"  {attachment.Filename} ({attachment.MimeType}, {attachment.Data.Length} bytes)");
    File.WriteAllBytes(attachment.Filename!, attachment.Data);
}

Вбудовані вкладення повідомлень також підтримуються. Коли MapiAttachment.IsEmbeddedMessage є true, властивість EmbeddedMessage повертає вкладений MapiMessage, який можна рекурсивно досліджувати.

Доступ до властивостей MAPI

Для просунутих сценаріїв кожне повідомлення, одержувач і вкладення надає Properties колекцію типу MapiPropertyCollection. Ви можете читати, додавати та видаляти окремі властивості MAPI за їхнім ідентифікатором властивості та кодом типу.

var message = MapiMessage.FromFile("custom-props.msg");

// Iterate all properties on the message
foreach (var prop in message.Properties.IterProperties())
{
    Console.WriteLine($"Tag: 0x{prop.PropertyTag:X8}, Value: {prop.Value}");
}

// Read a specific property
var subject = message.Properties.Get(
    (ushort)CommonMessagePropertyId.Subject,
    (ushort)PropertyTypeCode.PtypString);

Перечислення CommonMessagePropertyId визначає добре відомі ідентифікатори властивостей MAPI для базової семантики повідомлень, полів тіла, заголовків транспорту та метаданих вкладень.

Перетворення між MSG та EML

Проаналізоване повідомлення можна зберегти назад у будь-якому з форматів. Save() записує байти MSG, тоді як SaveToEml() генерує MIME-вивід. Це робить конвертацію форматів простою.

// Load an EML and save as MSG
var message = MapiMessage.LoadFromEml("incoming.eml");
message.Save("converted.msg");

// Load an MSG and save as EML
var msg = MapiMessage.FromFile("outgoing.msg");
msg.SaveToEml("exported.eml");

Обидва методи також приймають параметр Stream для обробки в пам’яті без доступу до файлової системи.


Швидкий старт

Встановіть пакет з NuGet:

dotnet add package Aspose.Email.FOSS

Тоді розберіть ваше перше повідомлення:

using Aspose.Email.Foss.Msg;

// Load an MSG file
var message = MapiMessage.FromFile("sample.msg");

Console.WriteLine($"Subject:     {message.Subject}");
Console.WriteLine($"From:        {message.SenderName} <{message.SenderEmailAddress}>");
Console.WriteLine($"Date:        {message.MessageDeliveryTime}");
Console.WriteLine($"Body length: {message.Body?.Length ?? 0} chars");

// List attachments
foreach (var att in message.Attachments)
    Console.WriteLine($"  Attachment: {att.Filename} ({att.Data.Length} bytes)");

// Convert to EML
message.SaveToEml("sample.eml");
Console.WriteLine("Saved as EML.");

Підтримувані формати

ФорматРозширенняЧитатиЗапис
Outlook MSG.msgТакТак
MIME (EML).emlТакТак
Compound File Binary.cfbТакТак

Відкритий код та ліцензування

Aspose.Email FOSS для .NET випущено під ліцензією MIT. Повний вихідний код доступний на GitHub за адресою aspose-email-foss/Aspose.Email-FOSS-for-.Net. Внески, повідомлення про проблеми та pull-request’и вітаються.


Початок роботи

Пов’язані ресурси