收到的电子邮件破碎

时间:2018-02-06 06:31:41

标签: c# imap

我通过简单的IMAP客户端收到附件的电子邮件:

class Program
{
    static StreamWriter sw = null;
    static TcpClient tcpc = null;
    static SslStream ssl = null;
    static string path;
    static StringBuilder sb = new StringBuilder();
    static byte[] dummy;
    string username = "user";
    string password = "pass";

    static void Main(string[] args)
    {
        try
        {
            path = Environment.CurrentDirectory + "\\emailresponse.txt";

            if (System.IO.File.Exists(path))
                System.IO.File.Delete(path);

            using (sw = new System.IO.StreamWriter(System.IO.File.Create(path)))
            using (tcpc = new System.Net.Sockets.TcpClient("imap.server.com", 993))
            using (ssl = new System.Net.Security.SslStream(tcpc.GetStream()))
            {
                ssl.AuthenticateAsClient("imap.server.com");
                receiveResponse("");                    
                receiveResponse("$ LOGIN " + username + " " + password + "\r\n");
                Console.WriteLine("enter the email number to fetch :");
                int number = int.Parse(Console.ReadLine());
                receiveResponse("$ FETCH " + number + " body[header]\r\n");
                receiveResponse("$ FETCH " + number + " body[text]\r\n");
                receiveResponse("$ LOGOUT\r\n");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    static void receiveResponse(string command)
    {
        try
        {
            if (command != "")
            {
                if (tcpc.Connected)
                {
                    dummy = Encoding.Default.GetBytes(command);
                    ssl.Write(dummy, 0, dummy.Length);
                }
                else
                {
                    throw new ApplicationException("TCP CONNECTION DISCONNECTED");
                }
            }
            ssl.Flush();
            byte[] bigBuffer = new byte[1024*18];
            int bites = ssl.Read(bigBuffer, 0, bigBuffer.Length);
            byte[] buffer = new byte[bites];
            Array.Copy(bigBuffer, 0, buffer, 0, bites);
            sb.Append(Encoding.Default.GetString(buffer));
            sw.WriteLine(sb.ToString());
            sb = new StringBuilder();
        }
        catch (Exception ex)
        {
            throw new ApplicationException(ex.ToString());
        }
    }
}

一切都很好,但如果电子邮件大小超过~19kb,则无论缓冲区大小如何,都会裁剪内容。如何解决?

2 个答案:

答案 0 :(得分:1)

如果调用Stream.Read(),则无法保证它将读取您要求的字节数。它只能保证它不会读取更多而不是你请求的字节数,并且它至少会读取1个字节,除非流已经达到了EOF (对于网络流,如果Stream.Read()返回0,则表示套接字已断开连接。)

正如其他人所指出的那样,你需要编写一个调用Stream.Read()的循环,直到你读完整个响应为止。

但是,请注意,在Read()返回0之前,您不能盲目地编写一个反复调用Stream.Read()的循环,因为这会导致代码挂起。您需要在阅读时正确解析响应,这样您就可以计算实际需要读取的数据量,并在阅读完整响应后停止阅读。

为了做到这一点,您需要阅读rfc3501并为其编写解析器。

由于您无法轻松地将byte []数据转换为字符串,直到您解析了消息内容(消息中的每个text / *部分可能编码在不同的字符集中),您将需要编写解析器,以便解析字节数组而不是字符串。

如果这听起来对您来说太多了,您可能需要考虑使用MailKit这样的库。

答案 1 :(得分:0)

解决方案是我必须重复请求receiveResponse("$ FETCH " + number + " body[text]\r\n"),直到我获得所有数据。问题是我在receiveResponse内循环而不是主块。