2011-06-07 40 views
5

我試圖使用TcpClient類連接到smtp.live.com。在這裏有一個很好的連接到Gmail的例子:Testing SMTP server is running via C#使用TcpClient類連接到smtp.live.com

不幸的是,當更新這個工作與smtp.live.com,我得到一個「IOException:由於意外的數據包格式握手失敗」 AuthenticateAsClient方法被調用。

我該如何解決這個問題?

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var client = new TcpClient()) 
     { 
      var server = "smtp.live.com"; 
      var port = 25; 
      client.Connect(server, port); 
      using (var stream = client.GetStream()) 
      using (var sslStream = new SslStream(stream)) 
      { 
       // Getting an IOException here 
       sslStream.AuthenticateAsClient(server); 
       using (var writer = new StreamWriter(sslStream)) 
       using (var reader = new StreamReader(sslStream)) 
       { 
        writer.WriteLine("EHLO " + server); 
        writer.Flush(); 
        Console.WriteLine(reader.ReadLine()); 
       } 
      } 
     } 
     Console.WriteLine("Press Enter to exit..."); 
     Console.ReadLine(); 
    } 
} 

我試過在AuthenticateAsClient中指定SslProtocol。 Tls或Ssl3都沒有工作。

還試圖提供RemoteCertificateValidation的回調,一直返回true,以防萬一服務器證書無效。那也行不通。

注意:請不要建議我使用SmtpClient;我需要比它提供的更多的控制。

+0

你需要什麼樣的控制是'SmtpClient'不提供? – jgauffin 2011-06-07 18:51:38

+0

我正在創建一個SMTP代理,它將支持來自我們內部不支持TLS/SSL的一些程序的未加密連接。 SMTP代理服務器將接受來自這些程序的連接,並將信息轉發到需要TLS/SSL的smtp.live.com服務器。 – 2011-06-08 12:42:14

+0

爲什麼你不能使用SmtpClient進行出站連接?聽起來只有代理中的inbount連接需要定製。 – jgauffin 2011-06-08 12:55:49

回答

11

感謝nos讓我走上正軌。該smtp.live.com服務器需要事件的順序如下:

  1. 連接
  2. HELO - 將不接受STARTTLS直到已發送
  3. STARTTLS - 顯然這臺服務器以接受加密連接
  4. SslStream.AuthenticateAsClient() - 這似乎讓C#框架和SMTP服務器來的「理解」 :)
  5. 現在,我們有一個加密的連接,通常的SMTP命令的工作

不管怎麼說,這個代碼同時適用於smtp.live.com和smtp.gmail.com端口587:

class Program 
{ 
    static void Main(string[] args) 
    { 
     const string server = "smtp.live.com"; 
     const int port = 587; 
     using (var client = new TcpClient(server, port)) 
     { 
      using (var stream = client.GetStream()) 
      using (var clearTextReader = new StreamReader(stream)) 
      using (var clearTextWriter = new StreamWriter(stream) { AutoFlush = true }) 
      using (var sslStream = new SslStream(stream)) 
      { 
       var connectResponse = clearTextReader.ReadLine(); 
       if (!connectResponse.StartsWith("220")) 
        throw new InvalidOperationException("SMTP Server did not respond to connection request"); 

       clearTextWriter.WriteLine("HELO"); 
       var helloResponse = clearTextReader.ReadLine(); 
       if (!helloResponse.StartsWith("250")) 
        throw new InvalidOperationException("SMTP Server did not respond to HELO request"); 

       clearTextWriter.WriteLine("STARTTLS"); 
       var startTlsResponse = clearTextReader.ReadLine(); 
       if (!startTlsResponse.StartsWith("220")) 
        throw new InvalidOperationException("SMTP Server did not respond to STARTTLS request"); 

       sslStream.AuthenticateAsClient(server); 

       using (var reader = new StreamReader(sslStream)) 
       using (var writer = new StreamWriter(sslStream) { AutoFlush = true }) 
       { 
        writer.WriteLine("EHLO " + server); 
        Console.WriteLine(reader.ReadLine()); 
       } 
      } 
     } 
     Console.WriteLine("Press Enter to exit..."); 
     Console.ReadLine(); 
    } 
} 
+0

不要忘記標記自己回答 – eFloh 2011-06-08 12:49:44

+1

@eFloh - 感謝您的提醒。所以我不會讓我這麼做......不得不等待24小時或一些這樣的。 – 2011-06-14 02:49:21

+1

我在CodePlex上用一個簡單的[SMTP Proxy](http://smtpproxy.codeplex.com)創建了一個項目。希望它能幫助其他人擺脫這個泡菜。 – 2011-06-14 02:53:36

2

如果你想在連接上使用ssl。對於tls,您應該使用端口465作爲ssl或587

提示:先嚐試一下沒有ssl,並在事情有效後再添加它。

鏈接:http://www.checktls.com/tests.html看到一些starttls的例子。

+0

或者通過檢查smtp服務器是否支持StartTLS來協商TLS。 – nos 2011-06-07 18:48:38

+0

你是對的......我試了465和587.不行。 – 2011-06-08 00:16:47

+0

@nos - 感謝提示。我想我找到了解決辦法。 – 2011-06-08 00:17:40