我正在使用C#和Microsoft .Net Compact Framework 1.0。我尝试使用System.Net.Sockets.NetworkStream
和TcpClient
类来实现POP3协议。我能够登录并接收电子邮件并使用某些电子邮件服务器保存附件。但是对于一些人来说,我一直遇到问题。
我通过发送List <Index>
命令来阅读电子邮件的大小。在某些情况下,我的尺寸明显小于实际值。例如,对于相同的电子邮件:
Actual size: 577860, Returned size: 421096 using Exchange 2007
Actual size: 561005, Returned size: 560997 using Exchange 2003
为什么我没有得到合适的尺寸?以下是我正在使用的代码。
电子邮件的大小永远不会与StringBuilder
程序结束时PopRead
的大小相匹配。我无法可靠地阅读电子邮件,因为电子邮件大小不可靠,DataAvailable
的{{1}}属性有时是假的,即使有更多数据可以读取。
我发现,当我尝试通过无线方式(使用数据计划)连接到电子邮件服务器时,NetworkStream
属性更频繁,而不是通过activesync使用计算机的互联网连接时。
如果有帮助,电子邮件服务器是Exchange 2003和Exchange 2007.
DataAvailable
以下过程用于获取电子邮件的大小:
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 :(得分:1)
您的错误可能在于您使用ASCIIEncoder。
来自MSDN:
要转换的数据,例如数据 从流中读取,可以使用 仅在顺序块中。在这 大小写,或者数据量是多少 大,它需要分为 更小的块,应用程序应该 使用解码器或编码器 由GetDecoder方法提供或 分别是GetEncoder方法。
由于您一次只进行一点解码,因此可能会错误地解码部分流。
我会更改您的代码以使用decoder,或者立即读取整个消息,然后使用GetString()成员对其进行解码。
作为额外的健全性检查,您可以使用RETR&lt; index&gt;的消息大小。返回并查看它是否与LIST返回的内容相匹配。如果它们不匹配,我至少会使用RETR返回的内容。
答案 1 :(得分:0)
POP3是一个棘手的协议。这么多不同的服务器要处理,很多都有自己模糊不清的怪癖。如果这是一个生产应用程序,我会认真考虑购买经过全面测试的第三方组件。
答案 2 :(得分:0)
由于电子邮件应该以句号结尾,我会进行此比较以终止循环。
而不是
if ((lngFetchMailSize != 0 && !bMoreData)
&& (iBytesRead < lngFetchMailSize)
&& numberOfTimesZeroBytesRead < 5)
{
bMoreData = true;
}
我会把它写成
if(!bMoreData
&& strBuffer.ToString(strBuffer.Length - 5, 5) != "\r\n.\r\n")
{
bMoreData = true;
}