0

I have to implement IMAP to use it in my own email client via C# and .NET Standard 2.0. During the task, I can use TcpClient and SslStream classes. The problem lies in getting response from the server. I can't find a common solution how to identify the end of the message. Such as SMTP has "\r\n.\r\n" in the end of each message, IMAP has no the same pattern (according to my research). The majority of IMAP messages ends with [TAG] [RESPONSE], for example A1 OK success, but there are some which ends with * OK Gimap... or * BAD Invalid.... I just wrote a few lines of code:

class Program
{
    static TcpClient tcp;
    static SslStream ssl;

    static void Main(string[] args)
    {
        tcp = new TcpClient("imap.gmail.com", 993);
        ssl = new SslStream(tcp.GetStream());
        ssl.AuthenticateAsClient("imap.gmail.com");

        ReceiveResponse("");
        while (true)
        {
            try
            {
                string query = Console.ReadLine();
                if (query == "exit") break;
                ReceiveResponse(query + "\r\n");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            } 
        }

        Console.WriteLine(ReceiveResponse("$ LOGOUT\r\n"));
        Console.ReadKey();
    }

    static string ReceiveResponse(string query)
    {
        StringBuilder sb = new StringBuilder();
        try
        {
            if (query != "")
            {
                if (tcp.Connected)
                {
                    byte[] dummy = Encoding.ASCII.GetBytes(query);
                    ssl.Write(dummy, 0, dummy.Length);
                }
                else
                {
                    throw new ApplicationException("TCP CONNECTION DISCONNECTED!!");
                }
            }
            ssl.Flush();

            byte[] buffer = new byte[1024];
            List<byte> response = new List<byte>();
            while (true) // ваш метод, который определит полный ответ
            {
                int bytesRead = ssl.Read(buffer, 0, 1024);
                if (bytesRead == 0)
                    throw new EndOfStreamException("err");
                string str = Encoding.UTF8.GetString(buffer).Replace("\0", "");
                sb.Append(str);
                if (/* PATTERN I NEED*/) break;
            }

            Console.WriteLine(sb.ToString());
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        return sb.ToString();
    }
}

As you understand, I need the pattern to identify the univocal end of the message or at least solution how to get full message from IMAP server.

P.S. I'm not English native speaker, and it would be nice if you could express your thougth in simple words. Thanks in advance.

VUser
  • 1
  • IMAP is a considerably more complex protocol than SMTP. And, before you could even get to the message you would need to authenticate, select the folder, .. and then you can fetch the message but still need to parse the structured information returned - i.e. way more than your code currently provides. If you do really want to implement IMAP yourself instead of using existing libraries please follow the (complex) [IMAP standard](https://tools.ietf.org/html/rfc3501). To get some idea see [wikipedia:imap](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol#Dialog_example). – Steffen Ullrich May 01 '18 at 12:57
  • I take into account that fact. At first I try to set a communication with a server - something like a kernel of protocol. It is a program which allow you communicate with server via IMAP queries. And the problem of this program is impossibility of identifying the end of response. – VUser May 01 '18 at 13:07
  • There is no simple way to find the end of the response. The exact semantics depend on the command and kind of response and you might need to parse parts of the response in order to find out where the response ends or where you can find more information you need to parse to find the end of the response. Really complicated. Again, read the standard or take a look at existing implementations. – Steffen Ullrich May 01 '18 at 13:15

1 Answers1

2

IMAP responses are either one line, or n section plus one lines. Four kinds of responses are just one line: OK, BYE, NO and BAD. The others are n sections, where each section is a line ending in {number} followed by that number of bytes, and one final line that does not end with the {number}.

The example on page 80 of RFC 3501 shows both kinds clearly. Note that even single lines can be very long, much longer than 1024 bytes in practice. The formal syntax starting on page 81 describes the details; I've left out some details on purpose.

Community
  • 1
  • 1
arnt
  • 8,949
  • 5
  • 24
  • 32