2015-12-17 4 views
0

J'ai une application qui analyse un compte de courrier électronique pour le courrier retourné. Il utilise POP3 et fonctionne avec succès sur les systèmes de plusieurs clients. Cependant, avec un client, lorsque nous essayons de nous connecter, nous recevons une exception SocketException - Aucun hôte de ce type n'est connu. Ma première pensée était que l'adresse ou le port n'étaient pas accessibles, mais ils sont revenus en disant qu'il s'agit d'un port SSL, et j'ai pensé que mon code pourrait ne pas être capable de gérer SSL. Cependant, l'erreur se produit quand j'appelle tcpClient = new TcpClient(Host, Port);, donc je suis de retour à mon hypothèse précédente. Existe-t-il un moyen particulier pour que TcpClient se connecte à un port SSL?Connexion à SSL en utilisant POP3

Ma deuxième question est de savoir s'il existe un moyen facile de convertir du code pour utiliser SSL sans créer fondamentalement une classe de connexion POP3 régulière et une classe de connexion SSL POP3? Je crois que je dois utiliser SslStream au lieu de StreamReader, ce qui signifie que je devrais modifier n'importe quel code qui accède au serveur POP3, puisque SslStream n'a pas une méthode ReadLine().

J'ai ajouté mon code de connexion initial ci-dessous (ou les bits importants).

try 
{ 
    tcpClient = new TcpClient(Host, Port); 
} 
catch (SocketException e) 
{ 
    logger.Log(...); 
    throw (e); 
} 
String response = ""; 

try 
{ 
    streamReader = new StreamReader(tcpClient.GetStream()); 

    // Log in to the account 
    response = streamReader.ReadLine(); 
    if (response.StartsWith("+OK")) 
    { 
     response = SendReceive("USER ", UserName.Trim() + "@" + Domain.Trim()); 
     if (response.StartsWith("+OK")) 
     { 
      response = SendReceive("PASS ", Password); 
     } 
    } 

    if (response.StartsWith("+OK")) 
     result = true; 
} 
catch (Exception e) 
{ 
    result = false; 
} 

La méthode SendReceive est assez simple:

private String SendReceive(String command, String parameter) 
{ 
    String result = null; 
    try 
    { 
     String myCommand = command.ToUpper().Trim() + " " + parameter.Trim() + Environment.NewLine; 
     byte[] data = System.Text.Encoding.ASCII.GetBytes(myCommand.ToCharArray()); 
     tcpClient.GetStream().Write(data, 0, data.Length); 
     result = streamReader.ReadLine(); 
    } 
    catch { } // Not logged in... 
    return result; 
} 

Il semble être principalement la méthode ReadLine() qui ne fonctionne pas, mais la lecture sur qui suggère qu'il est difficile de lire une ligne avec un flux puisque vous ne savez pas s'il est fini d'envoyer ou non. Est-ce le cas, ou dois-je juste écrire une méthode rapide pour lire jusqu'à ce que je frappe un \r ou \n?

Répondre

1

Pour répondre à votre première question, il n'y a pas de façon différente de se connecter à un port SSL, cela fonctionne exactement de la même manière.

En ce qui concerne votre deuxième question, un StreamReader encapsule un System.IO.Stream et un SslStream est juste une mise en œuvre de System.IO.Stream, afin que vous puissiez créer un StreamReader autour d'elle très bien.

Ce que vous devez faire est quelque chose comme ceci:

var stream = tcpClient.GetStream(); 

if (useSsl) { 
    var ssl = new SslStream (stream); 
    ssl.AuthenticateAsClient (Host, null, SslProtocols.Tls12, true); 
    stream = ssl; 
} 

streamReader = new StreamReader (stream); 

Bien sûr, vous aurez besoin de fixer votre méthode SendReceive() de ne pas utiliser de nouveau tcpClient.GetStream(), parce que vous aurez besoin d'utiliser le SslStream et pas le NetworkStream que tcpClient.GetStream() reviendra.

La meilleure façon de le faire est probablement juste passer la variable à SendReceive(), ou, je suppose stream, ajouter un membre Stream à votre classe comme vous probablement fait pour streamReader et tcpClient.

Bien sûr, une meilleure solution serait d'utiliser une bibliothèque pour cela, comme ma bibliothèque MailKit qui gère tout cela pour vous d'une manière beaucoup plus robuste que ce code ne :)

+0

Essayez d'utiliser Tls10 ou Tls11 , peut-être GMail ne supporte pas TLS v1.2. En outre, GMail ne prend pas en charge USER/PASS; il ne supporte que SASL AUTH. – jstedfast