C# 请帮助我解决使用POP3协议检索电子邮件时遇到的问题

C# 请帮助我解决使用POP3协议检索电子邮件时遇到的问题,c#,compact-framework,pop3,C#,Compact Framework,Pop3,我正在使用C#和Microsoft.Net Compact Framework 1.0。我尝试使用System.Net.Sockets.NetworkStream和TcpClient类来实现POP3协议。我能够登录和接收电子邮件,并将附件保存在一些电子邮件服务器上。但对一些人来说,我总是遇到问题 我通过发送List命令来读取电子邮件的大小。在某些情况下,我得到的大小明显小于实际值。例如,对于同一封电子邮件: Actual size: 577860, Returned size: 421096 u

我正在使用C#和Microsoft.Net Compact Framework 1.0。我尝试使用
System.Net.Sockets.NetworkStream
TcpClient
类来实现POP3协议。我能够登录和接收电子邮件,并将附件保存在一些电子邮件服务器上。但对一些人来说,我总是遇到问题

我通过发送
List
命令来读取电子邮件的大小。在某些情况下,我得到的大小明显小于实际值。例如,对于同一封电子邮件:

Actual size: 577860, Returned size: 421096 using Exchange 2007
Actual size: 561005, Returned size: 560997 using Exchange 2003
为什么我总是穿不上合适的尺码?下面是我正在使用的代码

电子邮件的大小与
PopRead
过程结束时的
StringBuilder
的大小不匹配。我无法可靠地阅读电子邮件,因为电子邮件大小不可靠,
NetworkStream
DataAvailable
属性有时为假,即使可以读取更多数据

我观察到,当我试图通过空中连接到电子邮件服务器(使用数据计划)时,与通过activesync使用计算机的internet连接时相比,
DataAvailable
属性更容易出错

如果有帮助,电子邮件服务器是Exchange2003和Exchange2007

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;
}
希望我提供了解决问题所需的所有信息。任何指向正确方向的帮助或指针都会有很大帮助

谢谢,

钱德拉。

POP3是一个棘手的协议。有这么多不同的服务器需要处理,许多服务器都有自己模糊的怪癖。如果这是一个生产应用程序,我会认真考虑购买一个第三方的组件进行了彻底的测试。 您的错误可能在于以您目前的方式使用AscienceOrder

发件人:

要转换的数据,例如数据 从流中读取,可以使用 仅在顺序块中。在这个 案例,或者如果数据量如此大 需要将其划分为 较小的块,应用程序应该 使用解码器或编码器 由GetDecoder方法提供,或 分别使用GetEncoder方法

由于您一次解码一点点,因此可能是错误地解码了部分流

我会将您的代码更改为使用,或者一次读取整个消息,然后使用GetString()成员对其进行解码


作为附加的健全性检查,您可以使用RETR返回的消息大小,并查看它是否与列表返回的消息匹配。如果它们不匹配,我至少会选择RETR返回的内容。

因为电子邮件应该以句点结束,所以我会进行此比较以终止循环

而不是

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

您好,我尝试了几个组件(试用版),但没有多大帮助。有些人不断抛出异常,当我不得不下载一个大的(大约3MB)附件时,我不断遇到OutOfMemory异常。如果你有什么建议就好了。谢谢,ChandraI在我写的POP3图书馆里偶尔也会遇到同样的问题。你解决问题了吗?如果是,您介意分享解决方案吗?
 if ((lngFetchMailSize != 0 && !bMoreData)
       && (iBytesRead < lngFetchMailSize)
       && numberOfTimesZeroBytesRead < 5)
  {
      bMoreData = true;
  }
  if(!bMoreData 
    && strBuffer.ToString(strBuffer.Length - 5, 5) != "\r\n.\r\n")
  {
       bMoreData = true;
  }