使用TcpClient类连接到smtp.live.com

时间:2011-06-07 18:39:26

标签: c# .net smtp

我正在尝试使用TcpClient类连接到smtp.live.com。这里有一个很好的连接Gmail的例子:Testing SMTP server is running via C#

不幸的是,当更新它以使用smtp.live.com时,我在调用AuthenticateAsClient方法时遇到“IOException:由于意外的数据包格式导致握手失败”。

我该如何解决这个问题?

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;我需要更多的控制权。

2 个答案:

答案 0 :(得分:12)

感谢nos让我走上正轨。 smtp.live.com服务器需要以下事件序列:

  1. 连接
  2. HELO - 在发送之前不接受STARTTLS
  3. STARTTLS - 显然这会将服务器设置为接受加密连接
  4. SslStream.AuthenticateAsClient() - 这似乎让C#框架和SMTP服务器达成“理解”:)
  5. 现在我们有一个加密连接,通常的SMTP命令可以正常工作
  6. 无论如何,此代码适用于端口587上的smtp.live.com和smtp.gmail.com:

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

答案 1 :(得分:2)

如果要在连接上使用ssl。您应该将端口465用于ssl,或将587用于tls。

提示:首先尝试不使用ssl,然后在工作完成后添加它。

链接:http://www.checktls.com/tests.html以查看一些简单的示例。