【问题标题】:Connecting to SSL using POP3使用 POP3 连接到 SSL
【发布时间】:2015-12-17 17:42:15
【问题描述】:

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

我的第一个想法是地址或端口无法访问,但他们回来说这是一个 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

【问题讨论】:

    标签: c# ssl pop3


    【解决方案1】:

    要回答您的第一个问题,连接到 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 库,它以比这段代码更强大的方式为您处理所有这些:)

    【讨论】:

    • 尝试使用 Tls10 或 Tls11,也许 GMail 不支持 TLS v1.2。另外,GMail 不支持 USER/PASS;它只支持 SASL AUTH。
    猜你喜欢
    • 1970-01-01
    • 2013-08-30
    • 1970-01-01
    • 2015-09-05
    • 2016-12-24
    • 2018-12-20
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多