2015-12-17 184 views
0

我有一個應用程序掃描電子郵件帳戶的返回郵件。它使用POP3,並在多個客戶端系統上成功運行。但是,對於一個客戶端,當我們嘗試連接時,我們得到一個SocketException - 沒有這樣的主機是已知的。使用POP3連接到SSL

我的第一個想法是無論是地址還是端口都無法訪問,但他們回來說它是一個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.StreamSslStream只是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和而不是NetworkStreamtcpClient.GetStream()將返回。

做到這一點的最簡單的方法可能是在stream變量只是傳遞給SendReceive(),或者,我想,一個Stream成員添加到您的類像你大概是streamReadertcpClient一樣。

當然,一個更好的解決辦法是使用庫這個功能,比如我MailKit庫,它負責處理所有這一切爲您在更強大的方式比這個代碼:)

+0

嘗試使用Tls10或Tls11 ,也許GMail不支持TLS v1.2。另外,GMail不支持USER/PASS;它只支持SASL AUTH。 – jstedfast