从 IMAP 服务器检索并列出电子邮件

检索和列出消息

如何获取邮箱中消息的标识信息

在检索和处理电子邮件时,您可以使用 Aspose.Email for .NET 最新版本提供的以下功能获取详细的标识信息,如序列号和唯一 ID:

Aspose.Email.ImapMessageInfo 类:表示 IMAP 邮箱中消息的标识信息。

ImapMessageInfo.SequenceNumber 属性:检索消息的序列号。

ImapMessageInfo.UniqueId 属性:检索消息的唯一标识符。

Aspose.Email.MailMessage.ItemId 属性:表示邮箱中消息的附加标识信息。

以下代码片段演示了如何获取 IMAP 邮箱中消息的标识信息:

  1. 创建该类的实例 ImapClient 类,通过提供必要的参数,如 IMAP 服务器主机、端口、电子邮件地址、密码和安全选项。
  2. 使用 ListMessages 方法,从 "INBOX" 文件夹检索消息列表。使用 Take(5) 方法将列表限制为前五条消息。
  3. 使用以下方式提取列出消息的序列号: SequenceNumber 每条消息的属性。
  4. 使用 FetchMessages 方法,使用前一步获取的序列号从服务器检索消息的完整详情。
  5. 遍历获取的消息,对每条消息检索并显示以下信息:
  • 消息的序列号。
  • ItemId.SequenceNumber 属性。
  • 消息的主题。
using (var client = new ImapClient(imapHost, port, emailAddress, password, securityOption))
{
    // List the first 5 messages from the inbox
    var msgs = client.ListMessages("INBOX").Take(5);
    
    // Get sequence numbers of the messages
    var seqIds = msgs.Select(t => t.SequenceNumber);
    
    // Fetch messages based on sequence numbers
    var msgsViaFetch = client.FetchMessages(seqIds);
    
    for (var i = 0; i < 5; i++)
    {
        var thisMsg = msgsViaFetch[i];
        Console.WriteLine($"Message ID: {seqIds.ElementAt(i)} SequenceNumber: {thisMsg.ItemId.SequenceNumber} Subject: {thisMsg.Subject}");
    }
}

列出来自服务器的 MIME 消息 ID

ImapMessageInfo 提供 MIME MessageId 用于在不提取完整邮件的情况下识别邮件。以下代码片段展示了如何列出 MIME messageId。

ImapClient client = new ImapClient();
client.Host = "domain.com";
client.Username = "username";
client.Password = "password";
    
try
{
    ImapMessageInfoCollection messageInfoCol = client.ListMessages("Inbox");
    foreach (ImapMessageInfo info in messageInfoCol)
    {
        // Display MIME Message ID
        Console.WriteLine("Message Id = " + info.MessageId);
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

从服务器列出消息

Aspose.Email 提供了一个含 2 个成员的重载变体 ListMessages() 根据查询检索指定数量的消息。以下代码片段展示了如何列出消息。


imapClient.SelectFolder("Inbox");
ImapQueryBuilder builder = new ImapQueryBuilder();
MailQuery query =
	builder.Or(
	builder.Or(
	builder.Or(
	builder.Or(
	builder.Subject.Contains(" (1) "),
	builder.Subject.Contains(" (2) ")),
	builder.Subject.Contains(" (3) ")),
	builder.Subject.Contains(" (4) ")),
	builder.Subject.Contains(" (5) "));
ImapMessageInfoCollection messageInfoCol4 = imapClient.ListMessages(query, 4);
Console.WriteLine((messageInfoCol4.Count == 4) ? "Success" : "Failure");

递归列出邮件

IMAP 协议支持递归列出邮箱文件夹中的邮件。这也有助于列出文件夹的子文件夹中的邮件。以下代码片段展示了如何递归列出邮件。

// Create an imapclient with host, user and password
ImapClient client = new ImapClient();
client.Host = "domain.com";
client.Username = "username";
client.Password = "password";
client.SelectFolder("InBox");
ImapMessageInfoCollection msgsColl = client.ListMessages(true);
Console.WriteLine("Total Messages: " + msgsColl.Count);

使用多连接列出邮件

ImapClient 提供了一个 UseMultiConnection 属性可用于在繁重操作时创建多个连接。您也可以通过使用 ImapClient.ConnectionsQuantity。以下代码片段演示了使用多连接模式列出邮件,并将其性能与单连接模式进行比较。

ImapClient imapClient = new ImapClient();
imapClient.Host = "<HOST>";
imapClient.Port = 993;
imapClient.Username = "<USERNAME>";
imapClient.Password = "<PASSWORD>";
imapClient.SupportedEncryption = EncryptionProtocols.Tls;
imapClient.SecurityOptions = SecurityOptions.SSLImplicit;

imapClient.SelectFolder("Inbox");
imapClient.ConnectionsQuantity = 5;
imapClient.UseMultiConnection = MultiConnectionMode.Enable;
DateTime multiConnectionModeStartTime = DateTime.Now;
ImapMessageInfoCollection messageInfoCol1 = imapClient.ListMessages(true);
TimeSpan multiConnectionModeTimeSpan = DateTime.Now - multiConnectionModeStartTime;

imapClient.UseMultiConnection = MultiConnectionMode.Disable;
DateTime singleConnectionModeStartTime = DateTime.Now;
ImapMessageInfoCollection messageInfoCol2 = imapClient.ListMessages(true);
TimeSpan singleConnectionModeTimeSpan = DateTime.Now - singleConnectionModeStartTime;
            
double performanceRelation = singleConnectionModeTimeSpan.TotalMilliseconds / multiConnectionModeTimeSpan.TotalMilliseconds;
Console.WriteLine("Performance Relation: " + performanceRelation);

使用分页列出邮件

在电子邮件服务器的邮箱中包含大量邮件的情况下,通常希望使用分页支持列出或检索邮件。Aspose.Email API的 ImapClient 让您能够使用分页支持从服务器检索消息。

///<summary>
/// This example shows the paging support of ImapClient for listing messages from the server
/// Available in Aspose.Email for .NET 6.4.0 and onwards
///</summary>
using (ImapClient client = new ImapClient("host.domain.com", 993, "username", "password"))
{
    try
    {
        int messagesNum = 12;
        int itemsPerPage = 5;
        MailMessage message = null;
        // Create some test messages and append these to server's inbox
        for (int i = 0; i < messagesNum; i++)
        {
            message = new MailMessage(
                "from@domain.com",
                "to@domain.com",
                "EMAILNET-35157 - " + Guid.NewGuid(),
                "EMAILNET-35157 Move paging parameters to separate class");
            client.AppendMessage(ImapFolderInfo.InBox, message);
        }

        // List messages from inbox
        client.SelectFolder(ImapFolderInfo.InBox);
        ImapMessageInfoCollection totalMessageInfoCol = client.ListMessages();
        // Verify the number of messages added
        Console.WriteLine(totalMessageInfoCol.Count);

        ////////////////// RETREIVE THE MESSAGES USING PAGING SUPPORT////////////////////////////////////

        List<ImapPageInfo> pages = new List<ImapPageInfo>();
        PageSettings pageSettings = new PageSettings();
        ImapPageInfo pageInfo = client.ListMessagesByPage(itemsPerPage, 0, pageSettings);
        Console.WriteLine(pageInfo.TotalCount);
        pages.Add(pageInfo);
        while (!pageInfo.LastPage)
        {
            pageInfo = client.ListMessagesByPage(itemsPerPage, pageInfo.NextPage.PageOffset, pageSettings);
            pages.Add(pageInfo);
        }
        int retrievedItems = 0;
        foreach (ImapPageInfo folderCol in pages)
            retrievedItems += folderCol.Items.Count;
        Console.WriteLine(retrievedItems);
    }
    finally
    {
    }
}

列出消息附件

要获取附件的名称、大小等信息而不下载附件数据,请尝试以下 API:

  • Aspose.Email.Clients.Imap.ImapAttachmentInfo - 表示附件信息。
  • Aspose.Email.Clients.Imap.ImapAttachmentInfoCollection - 表示一个集合。 ImapAttachmentInfo 类。
  • Aspose.Email.Clients.Imap.ListAttachments(int sequenceNumber) - 获取消息中每个附件的信息。

下面的代码示例及步骤将向您展示如何使用这些 API:

  1. 调用 ListMessages() 在 imapClient 对象上调用此方法。此方法将返回一个 ImapMessageInfoCollection,其中包含邮箱中消息的信息。
  2. 使用 foreach 循环遍历 messageInfoCollection 中的每条消息。
  3. 调用 ListAttachments() 在 imapClient 对象上调用此方法,传入消息对象的 SequenceNumber 属性作为参数。此方法将返回一个 ImapAttachmentInfoCollection,其中包含关于该消息附件的信息。
  4. 使用 foreach 循环遍历 attachmentInfoCollection 中的每个附件。
  5. 在内部循环中,您可以使用 attachmentInfo 对象的属性访问每个附件的信息。
var messageInfoCollection = imapClient.ListMessages();
    
foreach (var message in messageInfoCollection)
{
    var attachmentInfoCollection = imapClient.ListAttachments(message.SequenceNumber);

    foreach (var attachmentInfo in attachmentInfoCollection)
    {
        Console.WriteLine("Attachment: {0} (size: {1})", attachmentInfo.Name, attachmentInfo.Size);
    }
}

获取并保存消息

从服务器获取消息

ImapClient 类可以从 IMAP 服务器获取消息,并将消息以 EML 格式保存到本地磁盘。以下步骤用于将消息保存到磁盘:

  1. 创建该类的实例 ImapClient 类。
  2. 在 ImapClient 中指定主机名、端口、用户名和密码 构造函数.
  3. 使用以下方式选择文件夹 SelectFolder() 方法。
  4. 调用 ListMessages 方法以获取 ImapMessageInfoCollection 对象。
  5. 遍历 ImapMessageInfoCollection 集合,调用 SaveMessage() 方法,并提供输出路径和文件名。

以下代码片段展示了如何从服务器获取电子邮件并保存。

// Select the inbox folder and Get the message info collection
client.SelectFolder(ImapFolderInfo.InBox);
ImapMessageInfoCollection list = client.ListMessages();

// Download each message
for (int i = 0; i < list.Count; i++)
{
    // Save the EML file locally
    client.SaveMessage(list[i].UniqueId, dataDir + list[i].UniqueId + ".eml");
}

按降序获取消息

Aspose.Email 提供 ImapClient.ListMessagesByPage 方法,列出支持分页的消息。该方法的某些重载 ImapClient.ListMessagesByPage 接受 PageSettings 作为参数。 PageSettings 提供一个 AscendingSorting 属性,如果设置为 false,则返回按降序排列的电子邮件。

以下示例代码演示了 AscendingSorting 属性的 PageSettings 类用于更改电子邮件的顺序。

ImapClient imapClient = new ImapClient();
imapClient.Host = "<HOST>";
imapClient.Port = 993;
imapClient.Username = "<USERNAME>";
imapClient.Password = "<PASSWORD>";
imapClient.SupportedEncryption = EncryptionProtocols.Tls;
imapClient.SecurityOptions = SecurityOptions.SSLImplicit;

PageSettings pageSettings = new PageSettings { AscendingSorting = false };
ImapPageInfo pageInfo = imapClient.ListMessagesByPage(5, pageSettings);
ImapMessageInfoCollection messages = pageInfo.Items;

foreach (ImapMessageInfo message in messages)
{
    Console.WriteLine(message.Subject + " -> " + message.Date.ToString());
}

以 MSG 格式保存消息

要将电子邮件保存为 MSG 格式, ImapClient.FetchMessage() 需要调用该方法。它返回一个实例化的 MailMessage 类。该 MailMessage.Save() 随后可以调用该方法将消息保存为 MSG。以下代码片段展示了如何将消息保存为 MSG 格式。

// The path to the file directory.
string dataDir = RunExamples.GetDataDir_IMAP();

// Create an imapclient with host, user and password
ImapClient client = new ImapClient("localhost", "user", "password");

// Select the inbox folder and Get the message info collection
client.SelectFolder(ImapFolderInfo.InBox);
ImapMessageInfoCollection list = client.ListMessages();

// Download each message
for (int i = 0; i < list.Count; i++)
{
    // Save the message in MSG format
    MailMessage message = client.FetchMessage(list[i].UniqueId);
    message.Save(dataDir + list[i].UniqueId + "_out.msg", SaveOptions.DefaultMsgUnicode);
}

分组获取的消息

ImapClient 提供了一个 FetchMessages 接受序列号或唯一标识的可迭代对象并返回列表的方法 MailMessage。下面的代码片段演示了 FetchMessages 根据序列号和唯一标识获取邮件的方法。

ImapClient imapClient = new ImapClient();
imapClient.Host = "<HOST>";
imapClient.Port = 993;
imapClient.Username = "<USERNAME>";
imapClient.Password = "<PASSWORD>";
imapClient.SupportedEncryption = EncryptionProtocols.Tls;
imapClient.SecurityOptions = SecurityOptions.SSLImplicit;

ImapMessageInfoCollection messageInfoCol = imapClient.ListMessages();
Console.WriteLine("ListMessages Count: " + messageInfoCol.Count);
int[] sequenceNumberAr = messageInfoCol.Select((ImapMessageInfo mi) => mi.SequenceNumber).ToArray();
string[] uniqueIdAr = messageInfoCol.Select((ImapMessageInfo mi) => mi.UniqueId).ToArray();

IList<MailMessage> fetchedMessagesBySNumMC = imapClient.FetchMessages(sequenceNumberAr);
Console.WriteLine("FetchMessages-sequenceNumberAr Count: " + fetchedMessagesBySNumMC.Count);

IList<MailMessage> fetchedMessagesByUidMC = imapClient.FetchMessages(uniqueIdAr);
Console.WriteLine("FetchMessages-uniqueIdAr Count: " + fetchedMessagesByUidMC.Count);

递归获取文件夹并读取消息

在本文中,大多数 ImapClient 这些功能用于创建一个应用程序,递归列出 IMAP 服务器上的所有文件夹和子文件夹。它还将每个文件夹和子文件夹中的消息以 MSG 格式保存到本地磁盘。磁盘上的文件夹和消息按照与 IMAP 服务器相同的层次结构创建和保存。下面的代码片段展示了如何递归获取消息和子文件夹信息。

public static void Run()
{
    // Create an instance of the ImapClient class
    ImapClient client = new ImapClient();

    // Specify host, username, password, Port and SecurityOptions for your client
    client.Host = "imap.gmail.com";
    client.Username = "your.username@gmail.com";
    client.Password = "your.password";
    client.Port = 993;
    client.SecurityOptions = SecurityOptions.Auto;
    try
    {
        // The root folder (which will be created on disk) consists of host and username
        string rootFolder = client.Host + "-" + client.Username;

        // Create the root folder and List all the folders from IMAP server
        Directory.CreateDirectory(rootFolder);
        ImapFolderInfoCollection folderInfoCollection = client.ListFolders();
        foreach (ImapFolderInfo folderInfo in folderInfoCollection)
        {
            // Call the recursive method to read messages and get sub-folders
            ListMessagesInFolder(folderInfo, rootFolder, client);
        }
        // Disconnect to the remote IMAP server
        client.Dispose();
    }
    catch (Exception ex)
    {
        Console.Write(Environment.NewLine + ex);
    }

    Console.WriteLine(Environment.NewLine + "Downloaded messages recursively from IMAP server.");
}

/// Recursive method to get messages from folders and sub-folders
private static void ListMessagesInFolder(ImapFolderInfo folderInfo, string rootFolder, ImapClient client)
{
    // Create the folder in disk (same name as on IMAP server)
    string currentFolder = RunExamples.GetDataDir_IMAP();
    Directory.CreateDirectory(currentFolder);

    // Read the messages from the current folder, if it is selectable
    if (folderInfo.Selectable)
    {
        // Send status command to get folder info
        ImapFolderInfo folderInfoStatus = client.GetFolderInfo(folderInfo.Name);
        Console.WriteLine(folderInfoStatus.Name + " folder selected. New messages: " + folderInfoStatus.NewMessageCount + ", Total messages: " + folderInfoStatus.TotalMessageCount);

        // Select the current folder and List messages
        client.SelectFolder(folderInfo.Name);
        ImapMessageInfoCollection msgInfoColl = client.ListMessages();
        Console.WriteLine("Listing messages....");
        foreach (ImapMessageInfo msgInfo in msgInfoColl)
        {
            // Get subject and other properties of the message
            Console.WriteLine("Subject: " + msgInfo.Subject);
            Console.WriteLine("Read: " + msgInfo.IsRead + ", Recent: " + msgInfo.Recent + ", Answered: " + msgInfo.Answered);

            // Get rid of characters like ? and :, which should not be included in a file name and Save the message in MSG format
            string fileName = msgInfo.Subject.Replace(":", " ").Replace("?", " ");
            MailMessage msg = client.FetchMessage(msgInfo.SequenceNumber);
            msg.Save(currentFolder + "\\" + fileName + "-" + msgInfo.SequenceNumber + ".msg", SaveOptions.DefaultMsgUnicode);
        }
        Console.WriteLine("============================\n");
    }
    else
    {
        Console.WriteLine(folderInfo.Name + " is not selectable.");
    }

    try
    {
        // If this folder has sub-folders, call this method recursively to get messages
        ImapFolderInfoCollection folderInfoCollection = client.ListFolders(folderInfo.Name);
        foreach (ImapFolderInfo subfolderInfo in folderInfoCollection)
        {
            ListMessagesInFolder(subfolderInfo, rootFolder, client);
        }
    }
    catch (Exception) { }            
}

处理特殊消息信息

检索额外参数作为摘要信息

using (ImapClient client = new ImapClient("host.domain.com", "username", "password"))
{
    MailMessage message = new MailMessage("from@domain.com", "to@doman.com", "EMAILNET-38466 - " + Guid.NewGuid().ToString(), "EMAILNET-38466 Add extra parameters for UID FETCH command");

    // append the message to the server
    string uid = client.AppendMessage(message);

    // wait for the message to be appended
    Thread.Sleep(5000);

    // Define properties to be fetched from server along with the message
    string[] messageExtraFields = new string[] { "X-GM-MSGID", "X-GM-THRID" };

    // retreive the message summary information using it's UID
    ImapMessageInfo messageInfoUID = client.ListMessage(uid, messageExtraFields);

    // retreive the message summary information using it's sequence number
    ImapMessageInfo messageInfoSeqNum = client.ListMessage(1, messageExtraFields);

    // List messages in general from the server based on the defined properties
    ImapMessageInfoCollection messageInfoCol = client.ListMessages(messageExtraFields);

    ImapMessageInfo messageInfoFromList = messageInfoCol[0];

    // verify that the parameters are fetched in the summary information
    foreach (string paramName in messageExtraFields)
    {
        Console.WriteLine(messageInfoFromList.ExtraParameters.ContainsKey(paramName));
        Console.WriteLine(messageInfoUID.ExtraParameters.ContainsKey(paramName));
        Console.WriteLine(messageInfoSeqNum.ExtraParameters.ContainsKey(paramName));
    }
}

获取 List-Unsubscribe 头信息

List-Unsubscribe 标头包含用于取消订阅电子邮件列表(例如广告、新闻稿等)的 URL。要获取 List-Unsubscribe 标头,请使用 ListUnsubscribe 属性的 ImapMessageInfo 类。以下示例展示了该类的使用 ListUnsubscribe 获取 List-Unsubscribe 标头的属性。

ImapClient imapClient = new ImapClient();
imapClient.Host = "<HOST>";
imapClient.Port = 993;
imapClient.Username = "<USERNAME>";
imapClient.Password = "<PASSWORD>";
imapClient.SupportedEncryption = EncryptionProtocols.Tls;
imapClient.SecurityOptions = SecurityOptions.SSLImplicit;

ImapMessageInfoCollection messageInfoCol = imapClient.ListMessages();
foreach (ImapMessageInfo imapMessageInfo in messageInfoCol)
{
    Console.WriteLine("ListUnsubscribe Header: " + imapMessageInfo.ListUnsubscribe);
}