2011-06-07 34 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