使用POP3连接到SSL

本文关键字:SSL 连接 POP3 使用 | 更新日期: 2023-09-27 18:27:09

我有一个应用程序,可以扫描电子邮件帐户以查找返回的邮件。它使用POP3,并在多个客户端的系统上成功工作。然而,对于一个客户端,当我们尝试连接时,我们会得到一个SocketException——没有这样的主机是已知的。

我的第一个想法是地址或端口不可访问,但他们回来说这是SSL端口,我认为我的代码可能无法处理SSL。然而,当我调用tcpClient = new TcpClient(Host, Port);时,错误正在发生,所以我回到了以前的假设。TcpClient需要通过特殊方式连接到SSL端口吗?

我的第二个问题是,是否有一种简单的方法可以在不创建常规POP3连接类和SSL POP3连接类的情况下将代码转换为使用SSL?我认为我需要使用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

使用POP3连接到SSL

要回答您的第一个问题,没有不同的方法可以连接到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,而不是tcpClient.GetStream()将返回的NetworkStream

最简单的方法可能是将stream变量传递给SendReceive(),或者,我想,像对streamReadertcpClient所做的那样,向类中添加一个Stream成员。

当然,更好的解决方案是为此使用一个库,例如我的MailKit库,它以比此代码更健壮的方式为您处理所有这些:)