Как получить полный ответ от IMAP сервера - PullRequest
0 голосов
/ 01 мая 2018

Я должен реализовать IMAP, чтобы использовать его в своем почтовом клиенте через C # и .NET Standard 2.0. Во время выполнения задачи я могу использовать классы TcpClient и SslStream. Проблема заключается в получении ответа от сервера. Я не могу найти общее решение, как определить конец сообщения. Например, SMTP имеет «\ r \ n. \ R \ n» в конце каждого сообщения, IMAP не имеет такой же схемы (согласно моим исследованиям). Большинство сообщений IMAP оканчивается на [TAG] [RESPONSE], например A1 OK success, но есть и такие, которые оканчиваются на * OK Gimap... или * BAD Invalid.... Я просто написал несколько строк кода:

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();
    }
}

Как вы понимаете, мне нужен шаблон для определения однозначного конца сообщения или, по крайней мере, решение, как получить полное сообщение с сервера IMAP.

P.S. Я не являюсь носителем английского языка, и было бы неплохо, если бы вы могли выразить свою мысль простыми словами. Заранее спасибо.

1 Ответ

0 голосов
/ 01 мая 2018

IMAP-ответы - это либо одна строка, либо n раздел плюс одна строка. Четыре вида ответов - это всего лишь одна строка: OK, BYE, NO и BAD. Другие - это n разделов, где каждый раздел представляет собой строку, заканчивающуюся {number}, за которой следует это количество байтов, и одну заключительную строку, которая не заканчивается на {number}.

Пример на странице 80 RFC 3501 четко показывает оба вида. Обратите внимание, что даже отдельные строки могут быть очень длинными, намного длиннее, чем 1024 байта на практике. Формальный синтаксис , начиная со страницы 81 , описывает детали; Я специально пропустил некоторые детали.

...