none
Broken received emails RRS feed

  • Question

  • I'm getting email with attachments by simple IMAP client:

    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[] Buffer = new byte[1024*50];
                int bites = ssl.Read(Buffer, 0, Buffer.Length);
                byte[] buffer = new byte[bites];
                Array.Copy(Buffer, 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());
            }
        }
    }
    Everything is alright, but if email size is more than ~19kb, content is cropped regardless of buffer size. How to fix it? 

    I found that the buffer size bites is 16384 bits or less.

    Tuesday, February 6, 2018 12:03 PM

All replies

  • Maybe you should execute ssl.Read in a loop until the returned number is zero. Append each portion to a List<byte> using AddRange. When no more data, convert the list to array using ToArray, then obtain the string.

    • Proposed as answer by Fei HuModerator Tuesday, February 13, 2018 11:07 AM
    Tuesday, February 6, 2018 5:26 PM
  • Hello antom,

    Try the Msdn example.

     static string ReadMessage(SslStream sslStream)
            {
                // Read the  message sent by the client.
                // The client signals the end of the message using the
                // "<EOF>" marker.
                byte [] buffer = new byte[2048];
                StringBuilder messageData = new StringBuilder();
                int bytes = -1;
                do
                {
                    // Read the client's test message.
                    bytes = sslStream.Read(buffer, 0, buffer.Length);
    
                    // Use Decoder class to convert from bytes to UTF8
                    // in case a character spans two buffers.
                    Decoder decoder = Encoding.UTF8.GetDecoder();
                    char[] chars = new char[decoder.GetCharCount(buffer,0,bytes)];
                    decoder.GetChars(buffer, 0, bytes, chars,0);
                    messageData.Append (chars);
                    // Check for EOF or an empty message.
                    if (messageData.ToString().IndexOf("<EOF>") != -1)
                    {
                        break;
                    }
                } while (bytes !=0); 
                return messageData.ToString();
            }

    Hope above would be helpful.

    Best regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, February 7, 2018 7:11 AM
    Moderator
  • Unfortunately, I cannot use <EOF> marker. Looks like my stream has no it.
    Thursday, February 8, 2018 2:48 AM
  • Hello anton,

    You could detect the "bytes" variables, when the stream has no more data, the value will be 0. The "<EOF>" just is a custom sign that indicates the message ends. If possible, you also define a sign like above example.

    Best regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, February 8, 2018 9:27 AM
    Moderator
  • Just as a suggestion, why not use some existing solution?
    For instance you could check out GemBox.Email:

    static void Main(string[] args)
    {
        try
        {
            string path = Path.Combine(Environment.CurrentDirectory, "emailresponse.txt");
            string username = "user";
            string password = "pass";
        
            using (var writer = new StreamWriter(path, false))
            using (var imapClient = new GemBox.Email.Imap.ImapClient("imap.server.com"))
            {
                imapClient.LogOutput = writer;
        
                imapClient.Connect();
                imapClient.Authenticate(username, password);
        
                // ...
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    Thursday, February 8, 2018 11:22 AM
  • There is one more problem, I cannot use external packages in my network, it is isolated of internet.
    Thursday, February 8, 2018 11:38 AM
  • Hello Anton,

    Viorel_ suggest is correct, you need loop the ssl.read and detect the bytes amount.

    Best regards,

    Neil Hu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, February 13, 2018 11:09 AM
    Moderator