创建和管理 PST 文件

除了解析现有 PST 文件,Aspose.Email 还提供从零创建 PST 文件的方式。本文演示了如何创建 Outlook PST 文件并向其中添加子文件夹或邮件。

创建 PST 文件

要在本地磁盘上创建新的 PST 文件,您需要使用 PersonalStorage class. 使用此类,您可以在 .NET 应用程序中创建、读取和操作 PST 文件。仅用一行代码即可从零创建存储文件:

// Create new PST
using var pst = PersonalStorage.Create(path, FileFormatVersion.Unicode);

向 PST 添加子文件夹

通过访问根文件夹并调用以下方法,在 PST 文件的根目录添加子文件夹: AddSubFolder 方法。

以下代码片段演示了如何添加名为 Inbox 的子文件夹:

// Add new folder "Test"
pst.RootFolder.AddSubFolder("Inbox");

检查文件夹容器类

在创建新文件夹或向现有文件夹添加项目时,重要的是确保新项目或文件夹的容器类与父文件夹的容器类保持一致,以维护 PST 存储文件中的组织层次结构。为此,Aspose.Email 提供了 EnforceContainerClassMatching 属性的 FolderCreationOptions class. 该属性指定是否强制检查要添加的文件夹的容器类是否与父文件夹的容器类匹配。如果设置为 ’true’,当容器类不匹配时将抛出异常。默认值为 ‘false’。

以下代码示例演示了 EnforceContainerClassMatching 属性,用于控制在添加容器类不匹配的文件夹时是否抛出异常:

using (var pst = PersonalStorage.Create("storage.pst", FileFormatVersion.Unicode))
{
    // Create a standard Contacts folder with the IPF.Contacts container class.
    var contacts = pst.CreatePredefinedFolder("Contacts", StandardIpmFolder.Contacts);
    
    // An exception will not arise. EnforceContainerClassMatching is false by default.
    contacts.AddSubFolder("Subfolder1", "IPF.Note");
    
    // An exception will occur as the container class of the subfolder being added (IPF.Note) 
    // does not match the container class of the parent folder (IPF.Contact).
    contacts.AddSubFolder("Subfolder3", new FolderCreationOptions {EnforceContainerClassMatching = true, ContainerClass = "IPF.Note"});
}

注意:在强制容器类匹配时确保正确处理异常,以防在 PST 中创建文件夹时出现意外行为。

更改文件夹容器类

有时需要更改文件夹的容器类。常见的例子是将不同类型(约会、邮件等)的消息添加到同一文件夹中。在这种情况下,需要更改文件夹中所有元素的容器类,以便正确显示。以下代码片段演示如何为此目的更改 PST 中文件夹的容器类。

using var pst = PersonalStorage.FromFile("PersonalStorage1.pst);
var folder = pst.RootFolder.GetSubFolder("Inbox");

folder.ChangeContainerClass("IPF.Note");

向 PST 添加文件

Microsoft Outlook 的核心功能是管理电子邮件、日历、任务、联系人和日志条目。此外,还可以将文件添加到 PST 文件夹,生成的 PST 会记录已添加的文档。Aspose.Email 提供了将文件与邮件、联系人、任务和日志条目一起添加到 PST 文件夹的功能。以下代码片段展示了如何使用 Aspose.Email 向 PST 文件夹添加文档。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
using (var personalStorage = PersonalStorage.Create(dataDir + "Ps1_out.pst", FileFormatVersion.Unicode))
{
    var folder = personalStorage.RootFolder.AddSubFolder("Files");

    // Add Document.doc file with the "IPM.Document" message class by default.
    folder.AddFile(dataDir + "attachment_1.doc", null);
}

向 PST 文件添加消息

使用 Aspose.Email,您可以向已创建或加载的 PST 文件的子文件夹添加邮件。本文将两封邮件从磁盘添加到 PST 的 Inbox 子文件夹。请使用 PersonalStorageFolderInfo 用于向 PST 文件添加消息的类。要向 PST 文件的 Inbox 文件夹添加消息:

  1. 创建 FolderInfo 类的实例,并加载 Inbox 文件夹的内容。
  2. 通过调用以下方法,将磁盘中的邮件添加到 Inbox 文件夹: FolderInfo.AddMessage() 方法。该 FolderInfo 类公开了 AddMessages 该方法可向文件夹添加大量邮件,减少磁盘 I/O 并提升性能。

以下代码片段展示了如何向名为 Inbox 的 PST 子文件夹添加邮件。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Create new PST            
var personalStorage = PersonalStorage.Create(dataDir, FileFormatVersion.Unicode);

// Add new folder "Inbox"
personalStorage.RootFolder.AddSubFolder("Inbox");

// Select the "Inbox" folder
var inboxFolder = personalStorage.RootFolder.GetSubFolder("Inbox");

// Add some messages to "Inbox" folder
inboxFolder.AddMessage(MapiMessage.FromFile(RunExamples.GetDataDir_Outlook() + "MapiMsgWithPoll.msg"));

批量添加消息以提升性能

向 PST 添加单个邮件会导致更多磁盘 I/O 操作,可能降低性能。为提升性能,可批量向 PST 添加邮件,以最小化 I/O 操作。 AddMessages 此方法允许批量添加消息,可用于以下场景。此外, MessageAdded 当消息被添加到文件夹时触发的事件。

从另一个 PST 添加消息

要从另一个 PST 添加消息,请使用 FolderInfo.EnumerateMapiMessages 返回 IEnumerable<MapiMessage>:

using var srcPst = PersonalStorage.FromFile(@"source.pst", false);
using var destPst = PersonalStorage.FromFile(@"destination.pst");

// Get the folder by name
var srcFolder = srcPst.RootFolder.GetSubFolder("SomeFolder");
var destFolder = destPst.RootFolder.GetSubFolder("SomeFolder");

destFolder.MessageAdded += new MessageAddedEventHandler(OnMessageAdded);
destFolder.AddMessages(srcFolder.EnumerateMapiMessages());


// Handles the MessageAdded event.
static void OnMessageAdded(object sender, MessageAddedEventArgs e)
{
    Console.WriteLine($"Added: {e.EntryId}");
}

从目录添加消息

要从目录添加消息,请创建 GetMessages(string pathToDir) 命名的迭代器方法,返回 IEnumerable<MapiMessage>:

using var pst = PersonalStorage.FromFile(@"storage.pst");
var folder = pst.RootFolder.GetSubFolder("SomeFolder");
folder.MessageAdded += OnMessageAdded;
folder.AddMessages(GetMessages(@"MessageDirectory"));

// Named iterator method to read messages from directory.
static IEnumerable<MapiMessage> GetMessages(string pathToDir)
{
    string[] files = Directory.GetFiles(pathToDir, "*.msg");

    foreach (var file in files)
    {
        yield return MapiMessage.Load(file);
    }
}

// Handles the MessageAdded event.
static void OnMessageAdded(object sender, MessageAddedEventArgs e)
{
    Console.WriteLine($"Added: {e.EntryId}");
}

从磁盘加载邮件

以下代码片段展示了如何从磁盘加载邮件。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
private static void AddMessagesInBulkMode(string fileName, string msgFolderName)
{
    using (PersonalStorage personalStorage = PersonalStorage.FromFile(fileName))
    {
        FolderInfo folder = personalStorage.RootFolder.GetSubFolder("myInbox");
        folder.MessageAdded += OnMessageAdded;
        folder.AddMessages(new MapiMessageCollection(msgFolderName));
    }
}
static void OnMessageAdded(object sender, MessageAddedEventArgs e)
{
    Console.WriteLine(e.EntryId);
    Console.WriteLine(e.Message.Subject);
}

IEnumerable 实现

以下代码片段展示了 IEnumerable 实现的用法。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
public class MapiMessageCollection : IEnumerable<MapiMessage>
{
    private string path;

    public MapiMessageCollection(string path)
    {
        this.path = path;
    }

    public IEnumerator<MapiMessage> GetEnumerator()
    {
        return new MapiMessageEnumerator(path);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class MapiMessageEnumerator : IEnumerator<MapiMessage>
{
    private readonly string[] files;

    private int position = -1;

    public MapiMessageEnumerator(string path)
    {
        string path1 = RunExamples.GetDataDir_Outlook();
        files = Directory.GetFiles(path1);
    }

    public bool MoveNext()
    {
        position++;
        return (position < files.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public MapiMessage Current
    {
        get
        {
            try
            {
                return MapiMessage.FromFile(files[position]);
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
    public void Dispose()
    {
    }
}