使用 POP3 连接到 SSL
Connecting to SSL using POP3
我有一个应用程序可以扫描电子邮件帐户以查找退回的邮件。它使用 POP3,并在多个客户的系统上成功运行。但是,对于一个客户端,当我们尝试连接时,我们会收到 SocketException - 不知道这样的主机。
我的第一个想法是地址或端口无法访问,但他们回来说这是一个 SSL 端口,我认为我的代码可能无法处理 SSL。然而,当我调用tcpClient = new TcpClient(Host, Port);
时,错误发生了,所以我又回到了我之前的假设。 TcpClient 是否需要通过特殊方式连接到 SSL 端口?
我的第二个问题是,是否有一种简单的方法可以将代码转换为使用 SSL,而无需基本上创建常规 POP3 连接 class 和 SSL POP3 连接 class?我相信我需要使用 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
?
回答您的第一个问题,连接到 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
而不是 NetworkStream
tcpClient.GetStream()
将 return.
最简单的方法可能是将 stream
变量传递给 SendReceive()
,或者,我想,将 Stream
成员添加到 class就像你大概为 streamReader
和 tcpClient
.
所做的那样
当然,更好的解决方案是为此使用一个库,例如我的 MailKit 库,它以比这段代码更强大的方式为您处理所有这些:)
我有一个应用程序可以扫描电子邮件帐户以查找退回的邮件。它使用 POP3,并在多个客户的系统上成功运行。但是,对于一个客户端,当我们尝试连接时,我们会收到 SocketException - 不知道这样的主机。
我的第一个想法是地址或端口无法访问,但他们回来说这是一个 SSL 端口,我认为我的代码可能无法处理 SSL。然而,当我调用tcpClient = new TcpClient(Host, Port);
时,错误发生了,所以我又回到了我之前的假设。 TcpClient 是否需要通过特殊方式连接到 SSL 端口?
我的第二个问题是,是否有一种简单的方法可以将代码转换为使用 SSL,而无需基本上创建常规 POP3 连接 class 和 SSL POP3 连接 class?我相信我需要使用 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
?
回答您的第一个问题,连接到 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
而不是 NetworkStream
tcpClient.GetStream()
将 return.
最简单的方法可能是将 stream
变量传递给 SendReceive()
,或者,我想,将 Stream
成员添加到 class就像你大概为 streamReader
和 tcpClient
.
当然,更好的解决方案是为此使用一个库,例如我的 MailKit 库,它以比这段代码更强大的方式为您处理所有这些:)