Как использовать SSL в классе TcpClient - PullRequest
20 голосов
/ 04 декабря 2011

В .NET Framework есть класс TcpClient для получения электронной почты с почтового сервера.Класс TcpClient имеет 4 конструктора для соединения с сервером, которые принимают не более двух параметров.Он отлично работает с теми серверами, которые не используют SSL.Но gmail или многие другие провайдеры электронной почты используют SSL для IMAP.

Я могу подключиться к серверу Gmail, но не могу аутентифицироваться с помощью email_id и пароля.

Мой код для аутентификации пользователя:

public void AuthenticateUser(string username, string password)
{
    _imapSw.WriteLine("$ LOGIN " + username + " " + password);
    //_imapSw is a object of StreamWriter class
    _imapSw.Flush();
    Response();
}

Но этот код не может войти в систему.

Итак, как я могу использовать класс TcpClient для получения электронной почты, когда мне нужно использовать SSL?

Ответы [ 3 ]

40 голосов
/ 04 декабря 2011

Вы должны использовать SslStream вместе с TcpClient , а затем использовать SslStream для чтения данных, а не TcpClient.

Что-то вроде:

        TcpClient mail = new TcpClient();
        SslStream sslStream;

        mail.Connect("pop.gmail.com", 995);
        sslStream = new SslStream(mail.GetStream());

        sslStream.AuthenticateAsClient("pop.gmail.com");

        byte[] buffer = new byte[2048];
        StringBuilder messageData = new StringBuilder();
        int bytes = -1;
        do
        {
            bytes = sslStream.Read(buffer, 0, buffer.Length);

            Decoder decoder = Encoding.UTF8.GetDecoder();
            char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
            decoder.GetChars(buffer, 0, bytes, chars, 0);
            messageData.Append(chars);

            if (messageData.ToString().IndexOf("<EOF>") != -1)
            {
                break;
            }
        } while (bytes != 0);

        Console.Write(messageData.ToString());
        Console.ReadKey();

EDIT

Приведенный выше код просто подключится через Gmail к SSL и выведет содержимое тестового сообщения.Для входа в учетную запись gmail и выдачи команд вам необходимо выполнить что-то вроде:

        TcpClient mail = new TcpClient();
        SslStream sslStream;
        int bytes = -1;

        mail.Connect("pop.gmail.com", 995);
        sslStream = new SslStream(mail.GetStream());

        sslStream.AuthenticateAsClient("pop.gmail.com");

        byte[] buffer = new byte[2048];
        // Read the stream to make sure we are connected
        bytes = sslStream.Read(buffer, 0, buffer.Length);
        Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytes));

        //Send the users login details
        sslStream.Write(Encoding.ASCII.GetBytes("USER USER_EMAIL\r\n"));
        bytes = sslStream.Read(buffer, 0, buffer.Length);
        Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytes));

        //Send the password                        
        sslStream.Write(Encoding.ASCII.GetBytes("PASS USER_PASSWORD\r\n"));
        bytes = sslStream.Read(buffer, 0, buffer.Length);
        Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytes));

        // Get the first email 
        sslStream.Write(Encoding.ASCII.GetBytes("RETR 1\r\n"));
        bytes = sslStream.Read(buffer, 0, buffer.Length);
        Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytes));

Очевидно, без всего дублирования кода:)

2 голосов
/ 28 апреля 2017

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

            pmOffice pmO = new pmOffice();
            pmO.GetpmOffice(3, false);

            TcpClient mail = new TcpClient();
            SslStream sslStream;
            int bytes = -1;

            mail.Connect("outlook.office365.com", 993);
            sslStream = new SslStream(mail.GetStream());

            sslStream.AuthenticateAsClient("outlook.office365.com");

            byte[] buffer = new byte[2048];
            // Read the stream to make sure we are connected
            bytes = sslStream.Read(buffer, 0, buffer.Length);
            Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytes));

            //Send the users login details (insert your username & password in the following line
            sslStream.Write(Encoding.ASCII.GetBytes("$ LOGIN " + pmO.mailUsername + " " + pmO.mailPassword + "\r\n"));
            bytes = sslStream.Read(buffer, 0, buffer.Length);
            string strOut = Encoding.ASCII.GetString(buffer, 0, bytes);

            // Get the status of the inbox (# of messages)
            sslStream.Write(Encoding.ASCII.GetBytes("$ STATUS INBOX (messages)\r\n"));
            bytes = sslStream.Read(buffer, 0, buffer.Length);
            strOut = Encoding.ASCII.GetString(buffer, 0, bytes);
2 голосов
/ 04 декабря 2011

Вы можете обернуть NetworkStream, предоставленный TcpClient, в SslStream.Это обеспечит необходимую обработку SSL и сертификатов.

Возможно, вам придется вставить некоторый код обработчика для выполнения обратного вызова проверки сертификата, например, через ServicePointManager.ServerCertificateValidationCallback.

...