2015-12-17 5 views
0

У меня есть приложение, которое сканирует учетную запись электронной почты для возвращенной почты. Он использует POP3 и успешно работает в нескольких системах клиентов. Однако с одним клиентом, когда мы пытаемся подключиться, мы получаем исключение SocketException - такой хост не известен.Подключение к SSL с использованием POP3

Моя первая мысль заключалась в том, что либо адрес, либо порт были недоступны, но они вернулись, сказав, что это порт SSL, и я решил, что мой код не сможет обрабатывать SSL. Однако ошибка происходит, когда я звоню tcpClient = new TcpClient(Host, Port);, поэтому я вернулся к своей предыдущей гипотезе. Есть ли специальный способ, с помощью которого TcpClient необходимо подключиться к порту SSL?

Мой второй вопрос заключается в том, есть ли простой способ преобразования кода для использования SSL без создания обычного класса соединений POP3 и класса соединения SSL POP3? Я считаю, что мне нужно использовать SslStream вместо StreamReader, что означает, что мне нужно будет изменить любой код, который обращается к серверу POP3, так как SslStream не имеет метода ReadLine().

Я добавил свой первоначальный код подключения ниже (или важные бит).

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

SendReceive метод довольно прост:

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

Это, как представляется, в основном ReadLine() метод, который не работает, но читать на том, что говорит о том, что трудно прочитать строку, содержащую поток, так как вы не знаете, завершена ли передача или нет. Это так, или мне просто нужно написать быстрый метод для чтения, пока я не нажму \r или \n?

ответ

1

Чтобы ответить на ваш первый вопрос, нет другого способа подключения к порту SSL, он работает точно так же.

Что касается вашего второго вопроса, StreamReader обертывания System.IO.Stream и SslStream это просто реализация System.IO.Stream, так что вы можете создать StreamReader вокруг него просто отлично.

Что вам нужно сделать, это что-то вроде этого:

var stream = tcpClient.GetStream(); 

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

streamReader = new StreamReader (stream); 

Конечно, вам необходимо исправить метод SendReceive() не использовать tcpClient.GetStream() снова, потому что вы должны будете использовать SslStream и а не NetworkStream, что tcpClient.GetStream() вернется.

Самый простой способ сделать это, вероятно, просто передать переменную stream в SendReceive(), или, я полагаю, добавить Stream элемент к классу, как Вы, вероятно, сделал для streamReader и tcpClient.

Конечно, лучшим решением было бы использовать библиотеку для этого, например, как моя MailKit библиотека, которая обрабатывает все это для вас в гораздо более надежным способом, чем этот код делает :)

+0

Попробуйте использовать Tls10 или Tls11 , возможно, GMail не поддерживает TLS v1.2. Кроме того, GMail не поддерживает USER/PASS; он поддерживает только SASL AUTH. – jstedfast