Управление вложениями сообщения

Работа с вложениями в Outlook

Создание и сохранение сообщений Outlook (файлы MSG) объясняет, как создавать и сохранять сообщения, а также как создавать файлы MSG со вложениями. Эта статья объясняет, как работать с вложениями Microsoft Outlook с помощью Aspose.Email. Вложения из файла сообщения получаются и сохраняются на диск с использованием MapiMessage класс Вложения свойства. The Вложения свойство является коллекцией типа MapiAttachmentCollection класс.

Проверка типа вложения (Встроенное или обычное)

Встроенные и обычные вложения служат разным целям. Встроенные вложения визуально интегрированы в электронное письмо и обычно представляют собой изображения или медиафайлы. Обычные вложения — это отдельные файлы, прикрепленные к письму, и могут включать различные типы файлов. The MapiAttachment.IsInline свойство MapiAttachment Проверить, является ли вложение встроенным или обычным

Следующий пример кода извлекает и отображает информацию о каждом вложении в загруженном MapiMessage, включая их отображаемые имена и информацию о том, являются ли они встроенными вложениями.

var message = MapiMessage.Load(fileName);

foreach (var attach in message.Attachments)
{
    Console.WriteLine($"{attach.DisplayName} : {attach.IsInline}");
}

Проверка типа вложения (IsReference)

Этот MapiAttachment класс включает IsReference свойство, позволяющее разработчикам идентифицировать ссылочные вложения в сообщении. С помощью следующего примера кода можно проверить, является ли вложение ссылочным:

foreach (var attachment in msg.Attachments)
{
    if (attachment.IsReference)
    {
        // Process reference attachment
    }
}

Сохранение вложений из файлов MSG

Чтобы сохранить вложения из файла MSG:

  1. Итерируйтесь по MapiAttachmentCollection коллекцию и получайте отдельные вложения.
  2. Чтобы сохранить вложения, вызовите метод Save() класса MapiAttachment.

Следующий фрагмент кода показывает, как сохранить вложения на локальный диск.

// Create an instance of MapiMessage from file
MapiMessage message = MapiMessage.FromFile(dataDir + fileName);

// Iterate through the attachments collection
foreach (MapiAttachment attachment in message.Attachments)
{
    // Save the individual attachment
    attachment.Save(dataDir + attachment.FileName);
}

Извлечение вложений из MSG‑файлов, отформатированных как RTF

Для сообщений, отформатированных как RTF, следующий код может использоваться для различения и извлечения вложений, которые являются либо встроенными, либо отображаются как значок в теле сообщения. Следующий фрагмент кода показывает, как идентифицировать и извлечь встроенное вложение из MSG, отформатированного как RTF.


var eml = MapiMessage.Load("MSG file with RTF Formatting.msg");

foreach (var attachment in eml.Attachments)
{
    if (IsAttachmentInline(attachment))
    {
        try
        {
            SaveAttachment(attachment, Guid.NewGuid().ToString());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

static bool IsAttachmentInline(MapiAttachment attachment)
{
    foreach (var property in attachment.ObjectData.Properties.Values)
    {
        if (property.Name == "\x0003ObjInfo")
        {
            var odtPersist1 = BitConverter.ToUInt16(property.Data, 0);
            return (odtPersist1 & (1 << (7 - 1))) == 0;
        }
    }
    return false;
}

static void SaveAttachment(MapiAttachment attachment, string fileName)
{
    foreach (var property in attachment.ObjectData.Properties.Values)
    {
        if (property.Name == "Package")
        {
            using var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            fs.Write(property.Data, 0, property.Data.Length);
        }
    }
}

Получить вложенные почтовые сообщения

Встроенные OLE‑вложения также появляются в MapiMessage класс коллекции Attachment. Следующий пример кода разбирает файл сообщения в поисках вложенных сообщений и сохраняет их на диск. The MapiMessage статический метод FromProperties() класса может создать новое сообщение из вложенного вложения. Следующий фрагмент кода показывает, как получить вложения вложенных почтовых сообщений.

// Create a MapiMessage object from the individual attachment
MapiMessage getAttachment = MapiMessage.FromProperties(attachment.ObjectData.Properties);

// Convert the embedded message to a MailMessage and save it to disk
MailMessage mailMessage = getAttachment.ToMailMessage(new MailConversionOptions());
mailMessage.Save(dataDir + @"NestedMailMessageAttachments_out.eml", SaveOptions.DefaultEml);

Удалить вложения

Библиотека Aspose Outlook предоставляет возможность удалять вложения из файлов Microsoft Outlook Message (.msg):

  • Вызовите метод RemoveAttachments(). Он принимает путь к файлу сообщения в качестве параметра. Реализован как публичный статический метод, поэтому создавать объект не требуется.

Следующий фрагмент кода показывает, как удалить вложения.

MapiMessage.RemoveAttachments(dataDir + "AttachmentsToRemove_out.msg");

Также можно вызвать MapiMessage статический метод класса DestroyAttachments(). Он работает быстрее, чем RemoveAttachments(), потому что метод RemoveAttachments() парсит файл сообщения.

MapiMessage.DestroyAttachments(dataDir + "AttachmentsToDestroy_out.msg");

Добавление вложений MSG

Сообщение Outlook может содержать другие сообщения Microsoft Outlook во вложениях, как обычные, так и встроенные. The MapiAttachmentCollection предоставляет перегруженные члены Добавить метод для создания сообщений Outlook с обоими типами вложений:

  • Add(string name, byte[] data) – добавляет обычное вложение из массива байтов.
  • Add(string name, MapiMessage message) – добавляет другое сообщение Outlook как вложенное сообщение.

Следующий фрагмент кода показывает, как добавить оба типа вложений к сообщению.

MapiMessage message = new MapiMessage("from@test.com", "to@test.com", "Subj", "This is a message body");

// Add a regular attachment from a byte array
message.Attachments.Add("note.txt", File.ReadAllBytes(dataDir + "note.txt"));

// Add another Outlook message as an embedded message
MapiMessage attachMsg = MapiMessage.FromFile(dataDir + "Message.msg");
message.Attachments.Add("Weekly report.msg", attachMsg);

message.Save(dataDir + "WithAttachments_out.msg");

Добавление ссылочных вложений к MapiMessages

Этот ReferenceAttachmentOptions класс упрощает добавление ссылочных вложений, инкапсулируя все необходимые свойства в один объект.

Параметры ReferenceAttachmentOptions:

  • sharedLink: Полный общий ссылочный URL к вложению, предоставленный веб‑сервисом, где хранится файл.
  • url: расположение файла или URL ресурса.
  • providerName: имя поставщика ссылочного вложения (например, Google Drive, Dropbox).
  • Пример: Добавление ссылочного вложения с помощью ReferenceAttachmentOptions
var options = new ReferenceAttachmentOptions(
    "https://drive.google.com/file/d/1HJ-M3F2qq1oRrTZ2GZhUdErJNy2CT3DF/",
    "https://drive.google.com/drive/my-drive",
    "GoogleDrive");

// Add reference attachment
msg.Attachments.Add("Document.pdf", options);

Встраивание сообщений как вложения

Следующий фрагмент кода показывает, как вложить файл MSG в сообщение.

MapiMessage message = new MapiMessage("from@test.com", "to@test.com", "Subj", "This is a message body");
MapiMessage attachMsg = MapiMessage.FromFile(dataDir + "Message.msg");
message.Attachments.Add("Weekly report.msg", attachMsg);
message.Save(dataDir + "WithEmbeddedMsg_out.msg");

Чтение встроенных сообщений из вложений

В следующем фрагменте кода показано, как читать встроенные сообщения из вложений.

var message = MapiMessage.FromFile(fileName);
if (message.Attachments[0].ObjectData.IsOutlookMessage)
{
    var getData = message.Attachments[0].ObjectData.ToMapiMessage();
}

Вставка и замена вложения

метод. Однако его нельзя использовать для вставки вложения с PR_ATTACH_NUM = 4 (например) в коллекцию, где collection.Count = 2.

Вставка вложений в определённые места

API Aspose.Email предоставляет возможность вставить MSG‑вложение в родительский MSG с помощью метода Insert коллекции MapiAttachmentCollection: MapiAttachmentCollection Insert(int index, string name, MapiMessage msg). Следующий фрагмент кода показывает, как вставить вложение в определённое место.

var message = MapiMessage.FromFile(fileName);
var memoryStream = new MemoryStream();
message.Attachments[2].Save(memoryStream);
           
var getData = MapiMessage.FromStream(memoryStream);
message.Attachments.Insert(1, "new 11", getData);

Заменить содержимое вложения

Это можно использовать для замены содержимого встроенного вложения новыми данными с помощью метода Replace. Однако нельзя использовать это для вставки вложения с PR_ATTACH_NUM = 4 (например) в коллекцию, где collection.Count = 2. Следующий фрагмент кода показывает, как заменить содержимое вложения.

var message = MapiMessage.FromFile(fileName);
var memoryStream = new MemoryStream();
message.Attachments[2].Save(memoryStream);
var getData = MapiMessage.FromStream(memoryStream);
message.Attachments.Replace(1, "new 1", getData);

Переименование вложений в MapiMessage

Можно изменить значение свойства DisplayName во вложениях MapiMessage.

var msg = MapiMessage.Load(fileName);
msg.Attachments[0].DisplayName = "New display name 1";
msg.Attachments[1].DisplayName = "New display name 2";

Сохранение вложений из цифрово подписанных сообщений

В следующем примере кода загружается сообщение электронной почты из файла, после чего извлекается информация о вложениях, в частности выводится отображаемое имя каждого вложения и является ли оно встроенным в сообщение или нет: 

Извлечь встроенные OLE‑объекты из oledata.mso

Иногда встроенные OLE‑данные представлены как oledata.mso вложение в MapiAttachment и их нужно извлекать вручную. Эти oledata.mso файлы находятся в формате Microsoft Compound Document File (MCDF), и поддержка таких файлов выходит за рамки Aspose.Email. Тем не менее, Aspose.Email можно использовать в сочетании с другими библиотеками с открытым исходным кодом, например OpenMCDF, чтобы прочитать содержимое этих файлов и сохранить его на диск. Aspose.Email предоставляет InlineAttachmentExtractor класс для перечисления пакетов MSO, содержащихся в бинарных данных oledata.mso, которые затем могут быть переданы библиотеке чтения составных файлов для извлечения содержимого.

Когда тип тела сообщения – HTML (а не RTF) и в сообщении присутствуют OLE‑объекты, MapiPropertyTag.PR_ATTACH_DATA_OBJ свойство отсутствует. В этом случае информация об OLE‑объектах содержится в oledata.mso.

Чтобы извлечь содержимое с помощью Aspose.Email и OpenMCDF:

  • Перечислите пакеты MSO из бинарных данных oledata.mso вложение.
  • Для каждого OLE‑элемента прочитайте составной файл.
  • Прочитайте поток с именем CONTENTS.
  • Сохраните содержимое в FileStream.
// The path to the File directory
string dataDir = RunExamples.GetDataDir_Email();

MapiMessage msg = MapiMessage.FromFile(dataDir + "double.msg");
foreach (MapiAttachment mapiAttachment in msg.Attachments)
{
    if (mapiAttachment.LongFileName == "oledata.mso")
    {
        IDictionary<string, byte[]> oledata = InlineAttachmentExtractor.EnumerateMsoPackage(new MemoryStream(mapiAttachment.BinaryData));
        int index = 0;
        foreach (var oleItem in oledata)
        {
            // Using the OpenMCDF library
            CompoundFile cf = new CompoundFile(new MemoryStream(oleItem.Value));
            CFStream contents = cf.RootStorage.GetStream("CONTENTS");
            using (FileStream fs = File.OpenWrite(index + ".pdf"))
            {
                byte[] data = contents.GetData();
                fs.Write(data, 0, data.Length);
                fs.Flush();
                fs.Close();
            }
            index++;
        }
    }
}