web-dev-qa-db-fra.com

Comment utiliser SSL dans la classe TCPCLIent

Dans le cadre .NET, il existe une classe TcpClient pour récupérer des courriels à partir d'un serveur de messagerie. La classe TcpClient a 4 constructeurs à connecter avec le serveur qui prennent au plus deux paramètres. Cela fonctionne bien avec ces serveurs qui n'utilisent pas SSL. Mais Gmail ou de nombreux autres fournisseurs de messagerie utilisent SSL pour IMAP.

Je peux me connecter avec Gmail Server mais je ne peux pas authentifier avec courrier électronique et mot de passe.

Mon code pour authentifier l'utilisateur est

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

Mais ce code ne peut pas se connecter.

Alors, comment puis-je utiliser la classe TcpClient pour récupérer des courriels lorsque je dois utiliser SSL?

20

Vous devez utiliser le SSLStream avec le tcpclient puis utilisez la SSLStream pour lire les données plutôt que le TCPClient.

Quelque chose dans le sens de:

        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 [~ # ~ #]

Le code ci-dessus se connectera simplement via SSL à Gmail et émis le contenu d'un message de test. Pour vous connecter à un compte Gmail et à des commandes d'émission, vous devrez faire quelque chose dans le sens de:

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

Évidemment, sans toute la duplication du code :)

41
codingbadger

Vous pouvez envelopper le NetworkStream fourni par TcpClient avec un SslStream . Cela fournira la manipulation nécessaire de la SSL et des certificats.

Vous devrez peut-être insérer un code de gestionnaire pour effectuer un rappel de validation de certificat, par ex. par ServicePointManager.ServerCertificateValidationCallback .

2
Polynomial

Pour adapter la meilleure réponse ci-dessus spécifiquement à la question de l'authentification IMAP et IMAP, vous devrez modifier légèrement le code pour utiliser les commandes IMAP comme suit. Pour le débogage, vous pouvez définir des points d'arrêt juste après l'affichage des réponses du serveur.

            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
msleep01