如何解析电子邮件比OpenPop.dll更快

本文关键字:dll 更快 OpenPop 何解析 电子邮件 | 更新日期: 2023-09-27 18:09:48

可以使用OpenPop.dll。

    Pop3Client objPOP3Client = new Pop3Client();
    int intTotalEmail = 0;
    DataTable dtEmail = new DataTable();
    object[] objMessageParts;
    try
    {
        dtEmail = GetAllEmailStructure();
        if (objPOP3Client.Connected)
            objPOP3Client.Disconnect();
        objPOP3Client.Connect(strHostName, intPort, bulUseSSL);
        try
        {
            objPOP3Client.Authenticate(strUserName, new Common()._Decode(strPassword));
            intTotalEmail = objPOP3Client.GetMessageCount();
            AddMapping();
            for (int i = 1; i <= intTotalEmail; i++)
            {
                objMessageParts = GetMessageContent(i, ref objPOP3Client, dtExistMailList);
                if (objMessageParts != null && objMessageParts[0].ToString() == "0")
                {
                    AddToDtEmail(objMessageParts, i, dtEmail, dtUserList, dtTicketIDList, dtBlacklistEmails, dtBlacklistSubject, dtBlacklistDomains);
                }
            }
        }
        catch (Exception ex)
        {
        }
    }
    catch (Exception ex)
    {
        ParserLogError(ex, "GetAllEmail()");
    }
    finally
    {
        if (objPOP3Client.Connected)
            objPOP3Client.Disconnect();
    }
    // function
     public object[] GetMessageContent(int intMessageNumber, ref Pop3Client objPOP3Client, DataTable dtExistingMails)
  {
    object[] strArrMessage = new object[10];
    Message objMessage;
    MessagePart plainTextPart = null, HTMLTextPart = null;
    string strMessageId = "";
    try
    {
        strArrMessage[0] = "";
        strArrMessage[1] = "";
        strArrMessage[2] = "";
        strArrMessage[3] = "";
        strArrMessage[4] = "";
        strArrMessage[5] = "";
        strArrMessage[6] = "";
        strArrMessage[7] = null;
        strArrMessage[8] = null;
        strArrMessage[7] = "";
        strArrMessage[8] = "";
        objMessage = objPOP3Client.GetMessage(intMessageNumber);
        strMessageId = (objMessage.Headers.MessageId == null ? "" : objMessage.Headers.MessageId.Trim());
        if (!IsExistMessageID(dtExistingMails, strMessageId)) //check in data base message id is exists or not 
        {
            strArrMessage[0] = "0";
            strArrMessage[1] = objMessage.Headers.From.Address.Trim();     // From EMail Address
            strArrMessage[2] = objMessage.Headers.From.DisplayName.Trim(); // From EMail Name
            strArrMessage[3] = objMessage.Headers.Subject.Trim();// Mail Subject     
            plainTextPart = objMessage.FindFirstPlainTextVersion();
            strArrMessage[4] = (plainTextPart == null ? "" : plainTextPart.GetBodyAsText().Trim());
            HTMLTextPart = objMessage.FindFirstHtmlVersion();
            strArrMessage[5] = (HTMLTextPart == null ? "" : HTMLTextPart.GetBodyAsText().Trim());
            strArrMessage[6] = strMessageId;
            List<MessagePart> attachment = objMessage.FindAllAttachments();
            strArrMessage[7] = null;
            strArrMessage[8] = null;
            if (attachment.Count > 0)
            {
                if (attachment[0] != null && attachment[0].IsAttachment)
                {
                    strArrMessage[7] = attachment[0].FileName.Trim();
                    strArrMessage[8] = attachment[0];
                }
            }
        }
        else
        {
            strArrMessage[0] = "1";
        }
    }
    catch (Exception ex)
    {
        ParserLogError(ex, "GetMessageContent()");
    }
    return strArrMessage;
 }

但是,我想使它比上面的OpenPop.dll更快。所以,如果有其他的技术可以解析邮件,请告诉我。

请核对代码后告诉我。

Thanks in advance

如何解析电子邮件比OpenPop.dll更快

但是,我想使它比上面的OpenPop.dll更快。所以请让我了解是否有其他技术可以解析邮件。

在GetMessageContent()方法中,消耗大量时间的一个地方是:

objMessage = objPOP3Client.GetMessage(intMessageNumber);

下载消息的网络I/O部分无法真正优化,但是OpenPop。. NET的解析器很慢(基于我自己的性能测试)。

MimeKit比OpenPop快25倍。. NET解析电子邮件消息

OpenPop的主要性能问题之一。. NET的MIME解析器是使用StreamReader进行解析的事实(由于不必要的字符集转换,一次读取一行等,它很慢-我在这里分析了另一个使用StreamReader进行解析的电子邮件库:https://stackoverflow.com/a/18787176/87117)。

还有OpenPop的问题。. NET的解析器还使用Regex在解析/解码头字符串之前从头字符串中删除CFWS(注释和折叠空白)。这很贵。最好编写一个能够处理CFWS的标记器。

如果你对我用来优化MimeKit的其他一些技术感兴趣(与高度优化的C实现一样快或更快),我写了一些关于这个的博客文章:

MimeKit使用的优化技巧:第1部分

我在第一部分中谈到的优化的总结是替换像这样的循环,扫描一行的末尾:

while (*inptr != (byte) ''n')
    inptr++;

和一个更快的循环,像这样:

int* dword = (int*) inptr;
do {
    mask = *dword++ ^ 0x0A0A0A0A;
    mask = ((mask - 0x01010101) & (~mask & 0x80808080));
} while (mask == 0);
inptr = (byte*) (dword - 1);
while (*inptr != (byte) ''n')
    inptr++;

提高了20%的性能(尽管在非x86架构上,它要求'dword'是4字节对齐的)。

MimeKit使用的优化技巧:第2部分

在第2部分中,我讨论了如何编写一个更加优化的System.IO.MemoryStream版本。MemoryStream的问题是,它必须保持一个连续的内存块与内容,这意味着,当你写更多的数据到它,它必须调整其内部字节数组的大小,它必须复制的内容到新的数组(这是昂贵的,特别是一旦数据量在流很大)。

为了解决这个性能瓶颈,我编写了一个MemoryBlockStream,它不需要使用连续的内存块-它使用字节数组的链表。当当前缓冲区溢出时,它不必重新调整字节数组的大小,而是简单地分配另一个2048字节的数组,数据将溢出并将其附加到链表中。

注意:MimeKit本身只做电子邮件解析,它不做POP3或SMTP或IMAP。如果你想要这种功能,我也写了一个基于MimeKit的库,它也能做到这一点:MailKit

更新:

使用MailKit(按要求)下载/解析所有消息的示例代码:

using System;
using System.Net;
using MailKit.Net.Pop3;
using MailKit;
using MimeKit;
namespace TestClient {
    class Program
    {
        public static void Main (string[] args)
        {
            using (var client = new Pop3Client ()) {
                client.Connect ("pop.gmail.com", 995, true);
                // Note: since we don't have an OAuth2 token, disable
                // the XOAUTH2 authentication mechanism.
                client.AuthenticationMechanisms.Remove ("XOAUTH2");
                client.Authenticate ("joey@gmail.com", "password");
                int count = client.GetMessageCount ();
                for (int i = 0; i < count; i++) {
                    var message = client.GetMessage (i);
                    Console.WriteLine ("Subject: {0}", message.Subject);
                }
                client.Disconnect (true);
            }
        }
    }
}