2009-04-17 13 views
2

私はC#とMicrosoft .Net Compact Framework 1.0を使用しています。私はSystem.Net.Sockets.NetworkStreamTcpClientクラスを使ってPOP3プロトコルを実装しようとしました。私はログインして電子メールを受け取り、いくつかの電子メールサーバーで添付ファイルを保存することができます。しかし、いくつかは、私は問題にぶち当たっています。私の問題POP3プロトコルを使用して電子メールを取得するのを助けてください

List <Index>コマンドを送信して電子メールメッセージのサイズを確認しました。状況によっては、実際の値よりもかなり小さいサイズになります。たとえば、同じEMailの場合:

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

なぜ私は正しいサイズを取得できませんか?私が使用しているコードは次のとおりです。

PopRead手順の最後にStringBuilderのサイズと電子メールのサイズが決して一致しません。電子メールのサイズが信頼できるものではなく、NetworkStreamDataAvailableプロパティが誤って読み取られる可能性があるため、電子メールを確実に読み取ることができません。

activeesyncを使用してコンピュータのインターネット接続を使用する場合よりも、データプランを使用して電子メールサーバーに接続しようとすると、DataAvailableプロパティがfalseになることが頻繁に確認されました。

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; 
} 

です問題を解決するために必要な情報正しい方向のヘルプやポインタは、多くの助けになります。

ありがとう、
Chandra。

+0

として、私はそれを記述します。あなたの問題を解決しましたか?はいの場合は、ソリューションを共有してもよろしいですか? – moster67

答えて

0

POP3は微妙なプロトコルです。対処すべき数多くの異なるサーバー、多くは独自の不明瞭な特徴を持つサーバーです。これがプロダクションアプリの場合は、完全にテストされたサードパーティコンポーネントを購入することを真剣に検討します。

+0

こんにちは、 私はいくつかのコンポーネント(試用版)を試しましたが、あまり役に立ちませんでした。いくつかのスロー例外が残っていました。大きな(約3 MB)アタッチメントをダウンロードしなければならないとき、OutOfMemory例外が発生しました。あなたに提案があればいいと思う。 ありがとう、 チャンドラ –

1

あなたの誤りは、ASCIIエンコーダーの使用にあるかもしれません。 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; 
    } 
関連する問題