2009-04-17 2 views
2

C# 및 Microsoft .NET Compact Framework 1.0을 사용하고 있습니다. System.Net.Sockets.NetworkStreamTcpClient 클래스를 사용하여 POP3 프로토콜을 구현하려고했습니다. 로그인하여 이메일을 받고 첨부 파일을 일부 이메일 서버에 저장할 수 있습니다. 그러나 일부에서는 문제가 계속 발생합니다.POP3 프로토콜을 사용하여 전자 메일을 검색 할 때 도움을 받으십시오.

List <Index> 명령을 보내 전자 메일 메시지의 크기를 읽었습니다. 어떤 경우에는 실제 값보다 훨씬 작은 크기가됩니다. 예를 들어, 동일한 전자 메일의 경우 :

Actual size: 577860, Returned size: 421096 using Exchange 2007 
Actual size: 561005, Returned size: 560997 using Exchange 2003 

왜 내가 올바른 크기를 얻지 못합니까? 다음 코드는 제가 사용하고 있습니다.

절차 끝의 StringBuilder 크기와 이메일의 크기가 결코 일치하지 않습니다. 전자 메일의 크기가 신뢰할 수 없으며 NetworkStreamDataAvailable 속성이 때때로 읽을 수있는 데이터가더라도 false 인 경우가 있으므로 전자 메일을 안정적으로 읽을 수 없습니다.

activeesync를 통해 컴퓨터의 인터넷 연결을 사용할 때보 다 공중 (이메일 계획을 사용하여)을 통해 이메일 서버에 연결하려고 할 때 DataAvailable 속성이 거짓 인 경우가 더 많음을 확인했습니다.

private long GetMailSize(int index) 
{ 
    StringBuilder strBuffer = new StringBuilder(); 
    const string LISTError = "Unable to read server's reply for LIST command"; 
    if ((this.POPServer != null) && (this.nsPOP != null)) 
    { 
     if (!this.POPWrite("LIST " + index)) 
     { 
      return -1L; 
     } 
     if (!this.POPRead(strBuffer)) 
     { 
      this.Error = LISTError; 
      return -1L; 
     } 
     if (!this.IsOK(strBuffer)) 
     { 
      return -1L; 
     } 
     string strReturned = strBuffer.ToString(); 
     int pos1 = strReturned.IndexOf(" ", 3); 
     if (pos1 == -1) 
     { 
      this.Error = LISTError; 
      return -1L; 
     } 
     int pos2 = strReturned.IndexOf(" ", (int)(pos1 + 1)); 
     if (pos2 == -1) 
     { 
      this.Error = LISTError; 
      return -1L; 
     } 
     int pos3 = strReturned.IndexOf("\r\n", (int)(pos2 + 1)); 
     if (pos3 == -1) 
     { 
      this.Error = LISTError; 
      return -1L; 
     } 
     long mailSize = 0; 
     Int64.TryParse(strBuffer.ToString(pos2 + 1, pos3 - (pos2 + 1)).Trim(), out mailSize); 
     return mailSize; 
    } 
    this.Error = NotConnectedError; 
    return -1L; 
} 

희망 나는 모든 주었다 도움이된다면

는 전자 메일 서버는 다음 절차는 전자 메일 메시지의 크기를 가져 오는 데 사용됩니다 Exchange 2003 및 Exchange 2007

private bool POPRead(StringBuilder strBuffer, long lngFetchMailSize) 
{ 
    const int bufferSize = 1024; 

    byte[] inb; 
    if (enc == null) 
    { 
     enc = new ASCIIEncoding(); 
    } 

    try 
    { 
     if (lngFetchMailSize > 0 && lngFetchMailSize < (32 * bufferSize)) 
     { 
      // limit the size of the buffer as the amount of memory 
      // on Pocket PC is limited. 
      inb = new byte[lngFetchMailSize]; 
     } 
     else 
     { 
      inb = new byte[bufferSize]; 
     } 
     Array.Clear(inb, 0, inb.Length); 
     bool bMoreData = true; 
     long iBytesRead = 0L; 
     int bytesReadInThisRound = 0; 

     int numberOfTimesZeroBytesRead = 0; 

     while (bMoreData) 
     { 
      bytesReadInThisRound = this.nsPOP.Read(inb, 0, inb.Length); 
      iBytesRead += bytesReadInThisRound; 

      if (bytesReadInThisRound == 0) 
      { 
       numberOfTimesZeroBytesRead++; 
      } 
      else 
      {//If on a retry the data read is not empty, reset the counter. 
       numberOfTimesZeroBytesRead = 0; 
      } 

      strBuffer.Append(enc.GetString(inb, 0, bytesReadInThisRound)); 
      Array.Clear(inb, 0, bytesReadInThisRound); 
      // DataAvailable sometimes gives false even though there is 
      // more to be read. 
      bMoreData = this.nsPOP.DataAvailable; 
      // Use this number (5), since some servers sometimes give the size 
      // of the email bigger than the actual size. 
      if ((lngFetchMailSize != 0 && !bMoreData) 
       && (iBytesRead < lngFetchMailSize) 
       && numberOfTimesZeroBytesRead < 5) 
      { 
       bMoreData = true; 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     string errmessage = "Reading email Expected Size: " + lngFetchMailSize; 
     LogException.LogError(ex, errmessage, false, "oePPop.POPRead"); 
     Error = ex.Message + " " + errmessage; 
     return false; 
    } 
    finally 
    { 
     GC.Collect(); 
    } 
    return true; 
} 

있습니다 문제 해결에 필요한 정보 올바른 방향으로 도움이나 포인터가 도움이 될 것입니다.

감사합니다.
찬드라.

+0

로 작성합니다. 문제를 해결 했습니까? 그렇다면 솔루션을 공유하는 것이 좋습니까? – moster67

답변

0

POP3는 까다로운 프로토콜입니다. 많은 다른 서버가 처리해야합니다. 많은 서버가 자신의 모호한 단점을 가지고 있습니다. 이 앱이 프로덕션 앱이라면 철저히 테스트 된 타사 구성 요소를 구입하는 것이 좋습니다.

+0

안녕하세요, 두 가지 구성 요소 (시험 버전)를 사용해 보았지만 많은 도움이되지 않았습니다. 일부는 예외를 던지고, 나는 큰 (약 3 MB) 첨부 파일을 다운로드해야 할 때 OutOfMemory 예외로 계속 실행했다. 제안이 있으면 좋을 것입니다. 감사합니다. 찬드라 –

1

오류는 ASCIIEncoder를 사용하는 것과 관련이 있습니다. MSDN 가입일

는 :

데이터를 변환 할 수있는, 이러한 스트림으로부터 판독 된 데이터 같이 순차 블록 사용할 수있다. 이 경우, 또는 데이터의 양이 작은 블록들로 분할 될 필요가 있도록 크면 디코더 또는 각각 GetDecoder 법 GetEncoder 방법에 의해 제공된 인코더 사용해야 애플리케이션.

한 번에 조금씩 디코딩하고 있기 때문에 스트림 부분을 잘못 디코딩하는 것이 가능합니다.

코드를 변경하여 decoder을 사용하거나 전체 메시지를 한 번에 읽은 다음 GetString() 멤버로 코드를 디코딩합니다.

RETR < 인덱스 >이 반환하는 메시지 크기를 사용하여 LIST가 반환하는 메시지와 일치하는지 확인할 수 있습니다. 일치하지 않으면 적어도 RETR이 반환하는 것과 함께 갈 것입니다.

0

전자 메일은 마침표로 끝나야하므로이 비교를 통해 루프가 종료됩니다.

대신

if ((lngFetchMailSize != 0 && !bMoreData) 
     && (iBytesRead < lngFetchMailSize) 
     && numberOfTimesZeroBytesRead < 5) 
    { 
     bMoreData = true; 
    } 

의 나는 내가 쓰고 있어요 POP3 도서관에서 종종 같은 문제에 직면하고있어

if(!bMoreData 
    && strBuffer.ToString(strBuffer.Length - 5, 5) != "\r\n.\r\n") 
    { 
     bMoreData = true; 
    } 
관련 문제