2014-06-23 3 views
1

OpenPop.dll을 사용하는 것이 가능합니다.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. 그래서 메일을 파싱하기위한 다른 기술이 있다면 알려주십시오.

코드를 확인한 다음 알려주십시오.

사전

+0

OpenPop에 대한 나의 경험은 매우 좋으므로 _parse_ 이메일에 대한 나의 방법은 개선 될 수 있기 때문에 속도가 느립니다. 그러나 따라서 우리는'GetMessageContent'를 보여주고 _slow_가 실제로 무엇을 의미하는지 알려줄 필요가 있습니다. –

+0

빈 캐치 블록은 [나쁜 생각] (http://stackoverflow.com/questions/1234343/why-are-empty-catch-blocks-a-bad-idea)입니다. 거기에 예외가 있습니까? 또한,'objPOP3Client'에'using' 문을 사용하십시오. 그러면 수동으로'Disconnect '할 필요가 없으며 바깥 쪽'Try-Catch-Finally'를 제거 할 수 있습니다. –

+0

이제 모든 코드가 표시되고 인증되지 않은 사용자가 연결할 때 오류가 발생합니다. – user3567592

답변

6

감사하지만, 난 빨리 OpenPop.dll 상기 이외을 만들고 싶어. 그래서 다른 기술이 메일 구문 분석을 위해 존재 하는지를 알려주세요. 당신의 GetMessageContent() 메소드에서

, 시간의 방대한 양을 소모 한 장소는 다음과 같습니다

objMessage = objPOP3Client.GetMessage(intMessageNumber); 

네트워크 I/O의 정말 최적화 할 수 없다는 메시지를 다운로드하는 부분 만 OpenPop. NET의 파서가 느립니다 (내 성능 테스트를 기반으로).

MimeKit은 전자 메일 메시지를 구문 분석 할 때 OpenPop.NET보다 25 배 빠릅니다.

OpenPop.NET MIME 파서의 주요 성능 문제 중 하나는 파싱에 StreamReader를 사용한다는 것입니다 (불필요한 문자 집합 변환으로 인해 속도가 느려지고 한 번에 한 줄씩 읽음 등). 여기에서 구문 분석을 위해 StreamReader를 사용하는 다른 전자 메일 라이브러리 : https://stackoverflow.com/a/18787176/87117).

OpenPop.NET의 파서가 Parge/Decoding하기 전에 헤더 문자열에서 CFWS (주석 및 접기 공백)를 제거하기 위해 Regex를 사용한다는 문제가 있습니다. 이것은 비싸다. CFWS를 처리 할 수있는 좋은 토크 나이저를 작성하는 것이 훨씬 낫습니다.

Optimization Tricks used by MimeKit: Part 1

: 당신이 다른 기술의 일부에 관심이 있다면

나는, 나는이에 대한 몇 가지 블로그 게시물을 작성 (빠르거나 매우 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 바이트로 정렬되어야합니다. 2 부에서는

Optimization Tricks used by MimeKit: Part 2

, 나는 System.IO.MemoryStream의보다 최적화 된 버전을 쓰기에 대해 이야기. MemoryStream의 문제는 콘텐츠에 1 개의 연속 된 메모리 블록을 유지해야한다는 것입니다. 즉, 더 많은 데이터를 쓰고 내부 바이트 배열의 크기를 조정해야하므로 새 배열에 내용을 복사해야합니다. 특히 스트림의 데이터 양이 많은 경우 비용이 많이 듭니다.

이 성능 병목 현상을 해결하기 위해 연속적인 메모리 블록을 사용할 필요가없는 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 ("[email protected]", "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); 
      } 
     } 
    } 
} 
+0

jstedfast 한번 보여 주실 수 있습니까? – user3567592

+0

무엇을 시연 하시겠습니까? – jstedfast

+0

MimeKit을 사용하여 모든 메일 아이디를 구문 분석하는 방법을 알려주십시오. – user3567592