Управление сообщениями в файлах PST

Contents
[ ]

Получение информации о сообщениях из файла Outlook PST

В Чтение файлов PST и получение информации В предыдущей статье мы обсуждали, как загрузить файл Outlook PST и просмотреть его папки, чтобы получить их имена и количество сообщений в каждой. Эта статья объясняет, как прочитать все папки и подпапки в файле PST и отобразить информацию о сообщениях, например, тему, отправителя и получателей. Файл Outlook PST может содержать вложенные папки. Чтобы получить информацию о сообщениях из всех этих папок, а также из папок верхнего уровня, используйте рекурсивный метод для чтения всех папок. Ниже приведён фрагмент кода, показывающий, как читать файл Outlook PST и рекурсивно отображать содержимое папок и сообщений.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
public static void Run()
{            
    string dataDir = RunExamples.GetDataDir_Outlook();

    // Load the Outlook file
    string path = dataDir + "PersonalStorage.pst";

    try
    {
       
        // Load the Outlook PST file
        PersonalStorage personalStorage = PersonalStorage.FromFile(path);

        // Get the Display Format of the PST file
        Console.WriteLine("Display Format: " + personalStorage.Format);

        // Get the folders and messages information
        FolderInfo folderInfo = personalStorage.RootFolder;

        // Call the recursive method to display the folder contents
        DisplayFolderContents(folderInfo, personalStorage);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);               
    }            
}

/// <summary>
/// This is a recursive method to display contents of a folder
/// </summary>
/// <param name="folderInfo"></param>
/// <param name="pst"></param>
private static void DisplayFolderContents(FolderInfo folderInfo, PersonalStorage pst)
{
    // Display the folder name
    Console.WriteLine("Folder: " + folderInfo.DisplayName);
    Console.WriteLine("==================================");
    // Display information about messages inside this folder
    MessageInfoCollection messageInfoCollection = folderInfo.GetContents();
    foreach (MessageInfo messageInfo in messageInfoCollection)
    {
        Console.WriteLine("Subject: " + messageInfo.Subject);
        Console.WriteLine("Sender: " + messageInfo.SenderRepresentativeName);
        Console.WriteLine("Recipients: " + messageInfo.DisplayTo);
        Console.WriteLine("------------------------------");
    }

    // Call this method recursively for each subfolder
    if (folderInfo.HasSubFolders == true)
    {
        foreach (FolderInfo subfolderInfo in folderInfo.GetSubFolders())
        {
            DisplayFolderContents(subfolderInfo, pst);
        }
    }
}

Извлечение сообщений из файлов PST

В этой статье показано, как читать файлы Microsoft Outlook PST и извлекать из них сообщения. Затем сообщения сохраняются на диск в формате MSG.

Следующий фрагмент кода показывает, как извлечь сообщения из PST‑файла:

  • Используйте рекурсивный метод для обхода всех папок (включая вложенные) и вызовите метод PersonalStorage.ExtractMessage() чтобы получить сообщения Outlook в экземпляр MapiMessage класс.
  • После этого вызовите метод MapiMessage.Save() для сохранения сообщения либо на диск, либо в поток в формате MSG.
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
public static void Run()
{            
    // The path to the file directory.
    string dataDir = RunExamples.GetDataDir_Outlook();

    // Load the Outlook file
    string path = dataDir + "PersonalStorage.pst";

    try
    {
        // load the Outlook PST file
        PersonalStorage pst = PersonalStorage.FromFile(path);

        // get the Display Format of the PST file
        Console.WriteLine("Display Format: " + pst.Format);

        // get the folders and messages information
        FolderInfo folderInfo = pst.RootFolder;

        // Call the recursive method to extract msg files from each folder
        ExtractMsgFiles(folderInfo, pst);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }            
}

/// <summary>
/// This is a recursive method to display contents of a folder
/// </summary>
/// <param name="folderInfo"></param>
/// <param name="pst"></param>
private static void ExtractMsgFiles(FolderInfo folderInfo, PersonalStorage pst)
{
    // display the folder name
    Console.WriteLine("Folder: " + folderInfo.DisplayName);
    Console.WriteLine("==================================");
    // loop through all the messages in this folder
    MessageInfoCollection messageInfoCollection = folderInfo.GetContents();
    foreach (MessageInfo messageInfo in messageInfoCollection)
    {
        Console.WriteLine("Saving message {0} ....", messageInfo.Subject);
        // get the message in MapiMessage instance
        MapiMessage message = pst.ExtractMessage(messageInfo);
        // save this message to disk in msg format
        message.Save(message.Subject.Replace(":", " ") + ".msg");
        // save this message to stream in msg format
        MemoryStream messageStream = new MemoryStream();
        message.Save(messageStream);
    }

    // Call this method recursively for each subfolder
    if (folderInfo.HasSubFolders == true)
    {
        foreach (FolderInfo subfolderInfo in folderInfo.GetSubFolders())
        {
            ExtractMsgFiles(subfolderInfo, pst);
        }
    }
}

Идентификация типов элементов MAPI

Этот MapiItemType enum представляет тип элемента MAPI, который можно явно преобразовать в объект соответствующего класса, производного от IMapiMessageItem интерфейс. Таким образом пользователи могут избежать проверки MessageClass значение свойства до конвертации сообщения.

Следующий пример кода показывает, как определить тип элемента для конвертации:

foreach (var messageInfo in folder.EnumerateMessages())
{
    var msg = pst.ExtractMessage(messageInfo);

    switch (msg.SupportedType)
    {
        // Non-supported type. MapiMessage cannot be converted to an appropriate item type.
        // Just use in MSG format.
        case MapiItemType.None:
            break;
        // An email message. Conversion isn't required.
        case MapiItemType.Message:
            break;
        // A contact item. Can be converted to MapiContact.
        case MapiItemType.Contact:
            var contact = (MapiContact)msg.ToMapiMessageItem();
            break;
        // A calendar item. Can be converted to MapiCalendar.
        case MapiItemType.Calendar:
            var calendar = (MapiCalendar)msg.ToMapiMessageItem();
            break;
        // A distribution list. Can be converted to MapiDistributionList.
        case MapiItemType.DistList:
            var dl = (MapiDistributionList)msg.ToMapiMessageItem();
            break;
        // A Journal entry. Can be converted to MapiJournal.
        case MapiItemType.Journal:
            var journal = (MapiJournal)msg.ToMapiMessageItem();
            break;
        // A StickyNote. Can be converted to MapiNote.
        case MapiItemType.Note:
            var note = (MapiNote)msg.ToMapiMessageItem();
            break;
        // A Task item. Can be converted to MapiTask.
        case MapiItemType.Task:
            var task = (MapiTask)msg.ToMapiMessageItem();
            break;
    }
}

Поиск и извлечение сообщений

Aspose.Email предоставляет следующие перегруженные методы FolderInfo класс для фильтрации и получения сообщений:

Пагинация получения содержимого папки

При работе с большими папками PST получение всех сообщений сразу может быть неэффективным. Чтобы повысить производительность и контроль, Aspose.Email for .NET предлагает поддержку пагинации в FolderInfo.GetContents метод. Этот метод извлекает подмножество сообщений, соответствующих указанному запросу, начиная с заданного индекса и ограничивая их количеством. Это позволяет получать сообщения небольшими управляемыми пакетами. Метод принимает следующие параметры:

IList<MessageInfo> FolderInfo.GetContents(MailQuery query, int startIndex, int count)
  • query — фильтр, применяемый к сообщениям (необязательно)

  • startIndex — нулевой индекс, с которого начинать получение

  • count — количество сообщений для возврата

Пример кода ниже демонстрирует, как внедрить этот метод в проект:

// Load the PST file
using (var pst = PersonalStorage.FromFile(fileName))
{
    // Access a specific subfolder
    var folder = pst.RootFolder.GetSubFolder("Inbox");

    // Build a query to filter messages by sender address
    var queryBuilder = new PersonalStorageQueryBuilder();
    queryBuilder.From.Contains("report-service", true);

    // Define the page size
    int pageSize = 5;

    // Retrieve and process messages in pages
    for (int pageIndex = 0; pageIndex < 6; pageIndex++)
    {
        int startIndex = pageIndex * pageSize;

        // Get a page of messages
        var messages = folder.GetContents(queryBuilder.GetQuery(), startIndex, pageSize);

        foreach (MessageInfo messageInfo in messages)
        {
            // Output basic info about each message
            Console.WriteLine($"Subject: {messageInfo.Subject}, Sender: {messageInfo.SenderRepresentativeName}");
        }
    }
}

Сохранение сообщений напрямую из PST в поток

Чтобы сохранить сообщения из PST‑файла напрямую в поток, не извлекая MsgInfo для сообщений, используйте метод SaveMessageToStream(). Следующий фрагмент кода показывает, как сохранять сообщения напрямую из PST в поток.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// The path to the file directory.
string dataDir = RunExamples.GetDataDir_Outlook();

// Load the Outlook file
string path = dataDir + "PersonalStorage.pst";

// Save message to MemoryStream
using (PersonalStorage personalStorage = PersonalStorage.FromFile(path))
{
    FolderInfo inbox = personalStorage.RootFolder.GetSubFolder("Inbox");
    foreach (MessageInfo messageInfo in inbox.EnumerateMessages())
    {
        using (MemoryStream memeorystream = new MemoryStream())
        {
            personalStorage.SaveMessageToStream(messageInfo.EntryIdString, memeorystream);
        }
    }
}

// Save message to file
using (PersonalStorage pst = PersonalStorage.FromFile(path))
{
    FolderInfo inbox = pst.RootFolder.GetSubFolder("Inbox");
    foreach (MessageInfo messageInfo in inbox.EnumerateMessages())
    {
        using (FileStream fs = File.OpenWrite(messageInfo.Subject + ".msg"))
        {
            pst.SaveMessageToStream(messageInfo.EntryIdString, fs);
        }
    }
}

using (PersonalStorage pst = PersonalStorage.FromFile(path))
{
    FolderInfo inbox = pst.RootFolder.GetSubFolder("Inbox");
    
    // To enumerate entryId of messages you may use FolderInfo.EnumerateMessagesEntryId() method:
    foreach (string entryId in inbox.EnumerateMessagesEntryId())
    {
        using (MemoryStream ms = new MemoryStream())
        {
            pst.SaveMessageToStream(entryId, ms);
        }
    }
}            

Извлечь определённое количество сообщений

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

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
FolderInfo inbox = personalStorage.RootFolder.GetSubFolder("Inbox");

// Extracts messages starting from 10th index top and extract total 100 messages
MessageInfoCollection messages = inbox.GetContents(10, 100);

Получить общее количество элементов из PST

Aspose.Email предоставляет GetTotalItemsCount() метод PersonalStorage.Store свойство. Оно возвращает общее число сообщений, содержащихся в PST.

Следующий пример кода показывает, как получить общее количество элементов (сообщений, встреч, контактов и т.д.), хранящихся в файле PST:

using (var pst = PersonalStorage.FromFile("my.pst", false))
{
    var count = pst.Store.GetTotalItemsCount();
}

Извлечение вложений без извлечения полного сообщения

API Aspose.Email может использоваться для извлечения вложений из PST‑сообщений без предварительного извлечения полного сообщения. ExtractAttachments метод PersonalStorage можно использовать для этого. Следующий фрагмент кода показывает, как извлечь вложения без извлечения полного сообщения.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
string dataDir = RunExamples.GetDataDir_Outlook();

using (PersonalStorage personalstorage = PersonalStorage.FromFile(dataDir + "Outlook.pst"))
{
    FolderInfo folder = personalstorage.RootFolder.GetSubFolder("Inbox");

    foreach (var messageInfo in folder.EnumerateMessagesEntryId())
    {
        MapiAttachmentCollection attachments = personalstorage.ExtractAttachments(messageInfo);

        if (attachments.Count != 0)
        {
            foreach (var attachment in attachments)
            {
                if (!string.IsNullOrEmpty(attachment.LongFileName))
                {
                    if (attachment.LongFileName.Contains(".msg"))
                    {
                        continue;
                    }
                    else
                    {
                        attachment.Save(dataDir + @"\Attachments\" + attachment.LongFileName);
                    }
                }
            }
        }
    }
}

Извлечение получателей сообщений из PST‑файлов

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

по EntryD (используя ExtractRecipients(string entryId) метод PersonalStorage класс)

using (var pst = PersonalStorage.FromFile(fileName))
{  
    // Recipients are extracted using the entry ID
    var recipients = pst.ExtractRecipients("AAAAADzSMygQQFJOkKwVhb8v5EUkASAA");
}

из MessageInfo (используя MapiRecipientCollection ExtractRecipients(MessageInfo messageInfo) метод)

using (var pst = PersonalStorage.FromFile(fileName))
{  
    // The "Inbox" folder is obtained
    var folder = pst.RootFolder.GetSubfolder("Inbox");

    // Each message in the "Inbox" folder is iterated
    foreach (var messageInfo in folder.EnumerateMessages())
    {
        // Recipients are extracted from each message
        var recipients = pst.ExtractRecipients(messageInfo);
    }
}

Поиск сообщений и папок

Поиск по критерию

Файлы Personal Storage (PST) могут содержать огромное количество данных. Поиск данных, соответствующих определённому критерию, в таких больших файлах требует включения нескольких точек проверки в коде для фильтрации информации. С помощью PersonalStorageQueryBuilder класс, Aspose.Email позволяет искать конкретные записи в PST на основе заданных критериев поиска. В PST можно искать сообщения по параметрам поиска, таким как отправитель, получатель, тема, важность сообщения, наличие вложений, размер сообщения и даже ID сообщения. PersonalStorageQueryBuilder можно также использовать для поиска подпапок.

Поиск сообщений и папок в PST

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

  • Важность сообщения.
  • Класс сообщения.
  • Наличие вложений.
  • Размер сообщения.
  • Непрочитанные сообщения.
  • Непрочитанные сообщения с вложениями и
  • папки с определённым именем подпапки.
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// The path to the File directory.
string dataDir = RunExamples.GetDataDir_Outlook();

using (PersonalStorage personalStorage = PersonalStorage.FromFile(dataDir + "Outlook.pst"))
{
    FolderInfo folder = personalStorage.RootFolder.GetSubFolder("Inbox");
    PersonalStorageQueryBuilder builder = new PersonalStorageQueryBuilder();

    // High importance messages
    builder.Importance.Equals((int)MapiImportance.High);
    MessageInfoCollection messages = folder.GetContents(builder.GetQuery());
    Console.WriteLine("Messages with High Imp:" + messages.Count);

    builder = new PersonalStorageQueryBuilder();
    builder.MessageClass.Equals("IPM.Note");
    messages = folder.GetContents(builder.GetQuery());
    Console.WriteLine("Messages with IPM.Note:" + messages.Count);

    builder = new PersonalStorageQueryBuilder();
    // Messages with attachments AND high importance
    builder.Importance.Equals((int)MapiImportance.High);
    builder.HasFlags(MapiMessageFlags.MSGFLAG_HASATTACH);
    messages = folder.GetContents(builder.GetQuery());
    Console.WriteLine("Messages with atts: " + messages.Count);

    builder = new PersonalStorageQueryBuilder();
    // Messages with size > 15 KB
    builder.MessageSize.Greater(15000);
    messages = folder.GetContents(builder.GetQuery());
    Console.WriteLine("messags size > 15Kb:" + messages.Count);

    builder = new PersonalStorageQueryBuilder();
    // Unread messages
    builder.HasNoFlags(MapiMessageFlags.MSGFLAG_READ);
    messages = folder.GetContents(builder.GetQuery());
    Console.WriteLine("Unread:" + messages.Count);

    builder = new PersonalStorageQueryBuilder();
    // Unread messages with attachments
    builder.HasNoFlags(MapiMessageFlags.MSGFLAG_READ);
    builder.HasFlags(MapiMessageFlags.MSGFLAG_HASATTACH);
    messages = folder.GetContents(builder.GetQuery());
    Console.WriteLine("Unread msgs with atts: " + messages.Count);

    // Folder with name of 'SubInbox'
    builder = new PersonalStorageQueryBuilder();
    builder.FolderName.Equals("SubInbox");
    FolderInfoCollection folders = folder.GetSubFolders(builder.GetQuery());
    Console.WriteLine("Folder having subfolder: " + folders.Count);

    builder = new PersonalStorageQueryBuilder();
    // Folders with subfolders
    builder.HasSubfolders();
    folders = folder.GetSubFolders(builder.GetQuery());
    Console.WriteLine(folders.Count);
}

Поиск с параметром игнорирования регистра

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

using (PersonalStorage personalStorage = PersonalStorage.Create("CaseSensitivity.pst", FileFormatVersion.Unicode))
{
	FolderInfo folderinfo = personalStorage.CreatePredefinedFolder("Inbox", StandardIpmFolder.Inbox);
	folderinfo.AddMessage(MapiMessage.FromMailMessage(MailMessage.Load("Sample.eml")));
	PersonalStorageQueryBuilder builder = new PersonalStorageQueryBuilder();
	// IgnoreCase is True
	builder.From.Contains("automated", true);
	MailQuery query = builder.GetQuery();
	MessageInfoCollection coll = folderinfo.GetContents(query);
	Console.WriteLine(coll.Count);
}

Поиск тем сообщений по нескольким ключевым словам

Вы можете использовать MailQueryBuilder.Or метод для поиска сообщений, тема которых содержит хотя бы одно из указанных слов, как показано ниже:

var builder1 = new PersonalStorageQueryBuilder();
builder1.Subject.Contains("Review"); // 'Review' is key word for the search

var builder2 = new PersonalStorageQueryBuilder();
builder2.Subject.Contains("Error"); // 'Error' is also key word for the search

var queryBuilder = new PersonalStorageQueryBuilder();
queryBuilder.Or(builder1.GetQuery(), builder2.GetQuery()); // message subjects must contain 'Review' or 'Error' words

using (var storage = PersonalStorage.FromFile("example.pst"))
{
    var folderInfo = storage.RootFolder.GetSubFolder("Inbox");
    var messageInfos = folderInfo.GetContents(queryBuilder.GetQuery());

    foreach (var messageInfo in messageInfos)
    {
        Console.WriteLine(messageInfo.Subject);
    }
}

Манипулирование сообщениями

Перемещение элементов в другие папки

Aspose.Email позволяет перемещать элементы из исходной папки в другую папку в том же файле Personal Storage (PST). Это включает:

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

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

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET

using(PersonalStorage personalStorage = PersonalStorage.FromFile("test.pst"))
{
    FolderInfo inbox = personalStorage.GetPredefinedFolder(StandardIpmFolder.Inbox);
    FolderInfo deleted = personalStorage.GetPredefinedFolder(StandardIpmFolder.DeletedItems);
    FolderInfo subfolder = inbox.GetSubFolder("Subfolder");

    // Move folder and message to the Deleted Items
    personalStorage.MoveItem(subfolder, deleted);
    MessageInfoCollection contents = subfolder.GetContents();
    personalStorage.MoveItem(contents[0], deleted);

    // Move all inbox subfolders and subfolder contents to the Deleted Items
    inbox.MoveSubfolders(deleted);
    subfolder.MoveContents(deleted);
}

Обновить свойства сообщения

Иногда требуется обновить определённые свойства сообщений, например изменить тему, отметить важность сообщения и т.д. Обновление сообщения в PST‑файле с такими изменениями в свойствах сообщения можно выполнить с помощью FolderInfo.ChangeMessages метод. Эта статья показывает, как массово обновлять сообщения в PST‑файле при изменении их свойств. Следующий фрагмент кода демонстрирует, как обновлять свойства сообщений пакетно для множества сообщений в PST‑файле.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// The path to the File directory.
string dataDir = RunExamples.GetDataDir_Outlook() + "Sub.pst";

// Load the Outlook PST file
PersonalStorage personalStorage = PersonalStorage.FromFile(dataDir);
            
// Get Requierd Subfolder 
FolderInfo inbox = personalStorage.RootFolder.GetSubFolder("Inbox");

// find messages having From = "someuser@domain.com"
PersonalStorageQueryBuilder queryBuilder = new PersonalStorageQueryBuilder();
queryBuilder.From.Contains("someuser@domain.com");

// Get Contents from Query
MessageInfoCollection messages = inbox.GetContents(queryBuilder.GetQuery());

// Save (MessageInfo,EntryIdString) in List
IList<string> changeList = new List<string>();
foreach (MessageInfo messageInfo in messages)
{
    changeList.Add(messageInfo.EntryIdString);
}

// Compose the new properties
MapiPropertyCollection updatedProperties = new MapiPropertyCollection();
updatedProperties.Add(MapiPropertyTag.PR_SUBJECT_W, new MapiProperty(MapiPropertyTag.PR_SUBJECT_W, Encoding.Unicode.GetBytes("New Subject")));
updatedProperties.Add(MapiPropertyTag.PR_IMPORTANCE, new MapiProperty(MapiPropertyTag.PR_IMPORTANCE, BitConverter.GetBytes((long)2)));

// update messages having From = "someuser@domain.com" with new properties
inbox.ChangeMessages(changeList, updatedProperties);

Обновление пользовательских свойств

Иногда требуется пометить элементы, которые уже обработаны в PST‑файле. API Aspose.Email позволяет это сделать с помощью MapiProperty и MapiNamedProperty. Следующие методы полезны для реализации этой задачи.

  • ctor MapiNamedProperty(long propertyTag, string nameIdentifier, Guid propertyGuid, byte[] propertyValue)
  • ctor MapiNamedProperty(long propertyTag, long nameIdentifier, Guid propertyGuid, byte[] propertyValue)
  • FolderInfo.ChangeMessages(MapiPropertyCollection updatedProperties) – изменяет все сообщения в папке
  • PersonalStorage.ChangeMessage(string entryId, MapiPropertyCollection updatedProperties) – изменяет свойства сообщения
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET

public static void Run()
{
	// Load the Outlook file
	string dataDir = RunExamples.GetDataDir_Outlook() + "Sub.pst";
	using (PersonalStorage personalStorage = PersonalStorage.FromFile(dataDir))
	{
		FolderInfo testFolder = personalStorage.RootFolder.GetSubFolder("Inbox");

		// Create the collection of message properties for adding or updating
		MapiPropertyCollection newProperties = new MapiPropertyCollection();

		// Normal,  Custom and PidLidLogFlags named  property
		MapiProperty property = new MapiProperty(MapiPropertyTag.PR_ORG_EMAIL_ADDR_W,Encoding.Unicode.GetBytes("test_address@org.com"));
		MapiProperty namedProperty1 = new MapiNamedProperty(GenerateNamedPropertyTag(0, MapiPropertyType.PT_LONG),"ITEM_ID",Guid.NewGuid(),BitConverter.GetBytes(123));
		MapiProperty namedProperty2 = new MapiNamedProperty(GenerateNamedPropertyTag(1, MapiPropertyType.PT_LONG),0x0000870C,new Guid("0006200A-0000-0000-C000-000000000046"),BitConverter.GetBytes(0));
		newProperties.Add(namedProperty1.Tag, namedProperty1);
		newProperties.Add(namedProperty2.Tag, namedProperty2);
		newProperties.Add(property.Tag, property);
		testFolder.ChangeMessages(testFolder.EnumerateMessagesEntryId(), newProperties);
	}
}

private static long GenerateNamedPropertyTag(long index, MapiPropertyType dataType)
{
	return (((0x8000 | index) << 16) | (long)dataType) & 0x00000000FFFFFFFF;
}

Удалить сообщения

Эта статья показывает, как использовать FolderInfo класс для доступа к определённым папкам в файле PST. Чтобы удалить сообщения из подпапки Sent ранее загруженного или созданного файла PST:

  1. Создать экземпляр FolderInfo класс и загрузив его содержимым подпапки Sent.
  2. Удалите сообщения из папки Sent, вызвав FolderInfo.DeleteChildItem() метод и передача MessageInfo.EntryId в качестве параметра. Следующий фрагмент кода показывает, как удалить сообщения из подпапки Sent файла PST.
// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// The path to the File directory.
string dataDir = RunExamples.GetDataDir_Outlook() + "Sub.pst";

// Load the Outlook PST file
PersonalStorage personalStorage = PersonalStorage.FromFile(dataDir);

// Get the Sent items folder
FolderInfo folderInfo = personalStorage.GetPredefinedFolder(StandardIpmFolder.SentItems);

MessageInfoCollection msgInfoColl = folderInfo.GetContents();
foreach (MessageInfo msgInfo in msgInfoColl)
{
    Console.WriteLine(msgInfo.Subject + ": " + msgInfo.EntryIdString);
    if (msgInfo.Subject.Equals("some delete condition") == true)
    {
        // Delete this item
        folderInfo.DeleteChildItem(msgInfo.EntryId);
        Console.WriteLine("Deleted this message");
    }
}

Удалить папки

Вы можете удалить папку PST, переместив её в папку Deleted Items.

using (PersonalStorage pst = PersonalStorage.FromFile(@"test.pst"))
{
    FolderInfo deletedItemsFolder = pst.GetPredefinedFolder(StandardIpmFolder.DeletedItems);
    FolderInfo emptyFolder = pst.RootFolder.GetSubFolder("Empty folder");
	  FolderInfo someFolder = pst.RootFolder.GetSubFolder("Some folder");
    pst.MoveItem(emptyFolder, deletedItemsFolder);
	  pst.MoveItem(someFolder, deletedItemsFolder);
}

Преимущество этого метода в том, что удалённую папку можно легко восстановить.

FolderInfo someFolder = deletedItemsFolder.GetSubFolder("Some folder");
pst.MoveItem(someFolder, pst.RootFolder);

При необходимости вы также можете окончательно удалить папку из папки Deleted Items.

deletedItemsFolder.DeleteChildItem(emptyFolder.EntryId);

Этот DeleteChildItem() метод может использоваться для любых папок, если необходимо сразу и окончательно удалить подпапку, обходя папку Deleted Items.

FolderInfo someFolder = pst.RootFolder.GetSubFolder("Some folder");
pst.RootFolder.DeleteChildItem(someFolder.EntryId);

Удаление элементов из PST

Удалять элементы (папки или сообщения) из Personal Storage Table (PST), используя уникальный entryId, вызывая метод DeleteItem(string entryId) у PersonalStorage класс.

Следующий фрагмент кода можно использовать для вызова метода DeleteItem и передачи entryId в качестве параметра:

var pst = PersonalStorage.FromFile("sample.pst");

// ...

pst.DeleteItem(entryId);

// ...

Обратите внимание:

  • Этот метод навсегда удалит элемент из PST и не может быть отменён. Будьте осторожны при его использовании, чтобы избежать случайной потери данных.
  • Согласно стандартным соглашениям, убедитесь, что entryId действителен и соответствует существующему элементу в PST.
  • В противном случае будет выброшено исключение. Рекомендуется иметь резервную копию PST или внедрить меры для восстановления удалённых элементов при необходимости.

Массовое удаление

API Aspose.Email можно использовать для пакетного удаления элементов из файла PST. Это достигается с помощью DeleteChildItems() метод, который принимает список элементов Entry ID, указывающих на элементы для удаления. Ниже показан фрагмент кода, демонстрирующий удаление элементов пакетно из файла PST.

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// The path to the File directory.
string dataDir = RunExamples.GetDataDir_Outlook() + @"Sub.pst";
using (PersonalStorage personalStorage = PersonalStorage.FromFile(dataDir))
{
    // Get Inbox SubFolder from Outlook file
    FolderInfo inbox = personalStorage.RootFolder.GetSubFolder("Inbox");

    // Create instance of PersonalStorageQueryBuilder
    PersonalStorageQueryBuilder queryBuilder = new PersonalStorageQueryBuilder();

    queryBuilder.From.Contains("someuser@domain.com");
    MessageInfoCollection messages = inbox.GetContents(queryBuilder.GetQuery());
    IList<string> deleteList = new List<string>();
    foreach (MessageInfo messageInfo in messages)
    {
        deleteList.Add(messageInfo.EntryIdString);
    }

    // delete messages having From = "someuser@domain.com"
    inbox.DeleteChildItems(deleteList);
}

Восстановление мягко удалённых элементов из PST и OST‑файлов

Aspose.Email для .NET предоставляет метод восстановления мягко удалённых элементов из PST и OST‑файлов. Эта функциональность реализована через PersonalStorage класс, который включает FindAndExtractSoftDeletedItems метод. Этот метод позволяет находить и восстанавливать элементы, мягко удалённые, что даёт возможность восстановить важные данные, которые иначе могли бы быть утеряны. Восстановленные элементы сохраняются в соответствующих папках как .msg файлы, обеспечивая сохранение исходной структуры папок. Пример кода ниже демонстрирует, как реализовать эту функцию в вашем проекте:

using (var pst = PersonalStorage.FromFile(fileName))
{
    // Soft deleted items are found and extracted
    var entries = pst.FindAndExtractSoftDeletedItems();

    // The recovered items are iterated through
    for (var index = 0; index < entries.Count; index++)
    {
        // Folder information is obtained by ID
        var folderInfo = pst.GetFolderById(entries[index].FolderId);

        // A directory for the folder is created if it doesn't exist
        if (!Directory.Exists(folderInfo.DisplayName))
        {
            Directory.CreateDirectory(Path.Combine(path, folderInfo.DisplayName));
        }
        
        // The restored item is obtained
        var msg = entries[index].Item;
        
        // The restored item is saved as a .msg file
        msg.Save(Path.Combine(path, folderInfo.DisplayName, $"{index}.msg"));
    }
}

Перечисление мягко удалённых сообщений в PST‑файлах

Мягко удалённые сообщения в PST‑файле – это элементы, удалённые дважды: сначала перемещённые в Deleted Items, затем удалённые снова. Такие сообщения не удаляются окончательно и могут быть получены программно. Aspose.Email для .NET поддерживает извлечение этих мягко удалённых сообщений для обзора или восстановления.

Чтобы перечислить и восстановить элементы, мягко удалённые (удалённые дважды) в PST‑файлах, используйте FindAndEnumerateSoftDeletedItems() метод. Этот метод возвращает перечислимый список таких элементов, каждый из которых включает сообщение и ID папки, из которой оно было удалено.

Следующий фрагмент кода демонстрирует, как перечислять и восстанавливать письма, удалённые дважды. Он возвращает RestoredItemEntry класс, представляющий запись для мягко удалённого элемента, восстановленного из PST‑файла. Класс содержит следующие свойства:

  • Item (MapiMessage): Восстановленный объект сообщения.

  • FolderId (string): Идентификатор папки, из которой сообщение было изначально удалено.

// Load the PST file
using (var pst = PersonalStorage.FromFile("archive.pst"))
{
    // Enumerate soft-deleted items
    foreach (var entry in pst.FindAndEnumerateSoftDeletedItems())
    {
        var message = entry.Item;
        var folderId = entry.FolderId;

        Console.WriteLine($"Subject: {message.Subject}");
        Console.WriteLine($"Deleted from Folder ID: {folderId}");
        Console.WriteLine("-----------------------------------");
    }
}

Разделить файлы PST

Разделить на несколько PST

Aspose.Email API предоставляет возможность разбить один файл PST на несколько файлов PST желаемого размера.

Ниже приведён пример кода, описывающий процесс разделения файла:

  1. Сначала он использует FromFile метод PersonalStorage класс для указания имени файла.

  2. Затем он вызывает StorageProcessedEventHandler делегат для обработки события StorageProcessed.

  3. StorageProcessingEventArgs предоставляет данные для события PersonalStorage.StorageProcessing. Его StorageProcessingEventArgs.FileName свойство позволяет получить имя PST‑файла. Для MergeWith метод будет именем текущего PST, который необходимо объединить с основным, и для SplitInto метод будет именем текущей части.

  4. Наконец, SplitInto(long chunkSize, string partFileNamePrefix, string path) Перегруженный метод запустит разделение хранилища PST на части меньшего размера. Он принимает следующие параметры:

  • chunkSize: Приблизительный размер каждой части в байтах.
  • partFileNamePrefix: Префикс, добавляемый к имени файла каждой части PST. Если указан, префикс будет добавлен в начало имени каждого файла. Если не указан (null или пусто), части PST будут созданы без префикса.
  • path: Путь к папке, в которой будут созданы части.

Имя файла каждой части формируется по шаблону: {prefix}part{number}.pst, где {prefix} – префикс имени файла (если указан), а {number} – номер части файла.

var pst = PersonalStorage.FromFile("sample.pst");

// ...

pst.StorageProcessing += (sender, args) =>
{
    Console.WriteLine("Storage processing event raised for file: " + args.FileName);
};

// ...

pst.SplitInto(5000000, "prefix_", outputFolderPath);

Разделить PST по заданному критерию

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

Объединить PST‑файлы

Объединить в один PST

Он также может объединять несколько PST‑файлов в один PST‑файл. Как операции разрезания, так и объединения PST можно отслеживать, добавляя события к этим операциям.

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

Объединить папки из другого PST

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