如果没有 connection/authentication MailKit,则移动到另一个客户端
Move to another client if there is no connection/authentication MailKit
我正在使用 mailkit 访问 pop3clients 列表。出于测试目的,我有一个不会进行身份验证的客户端,我写了一个 if 语句来进行身份验证 true 来完成一些任务。但是它没有移动到另一个客户端,而是抛出异常并停止进程。我应该实现什么或添加到我的代码中以便能够在没有连接或身份验证的情况下移动到另一个客户端。
public void connect(){
try
{
foreach (ObjectDeserializer obj in mailDeserialization.ListOfObjects())
{
Console.WriteLine(obj.toString());
if (obj.port == 995)
{
using (Pop3Client client = new Pop3Client())
{
client.CheckCertificateRevocation = false;
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(obj.server, obj.port, SecureSocketOptions.Auto);
client.Authenticate(obj.user, obj.password);
if (client.IsAuthenticated == true)
{
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
Console.WriteLine(message.From.ToString());
}
}
}
}
else
{
using (Pop3Client clientNoSSL = new Pop3Client(new ProtocolLogger("pop3.log")))
{
clientNoSSL.Connect(obj.server, obj.port, SecureSocketOptions.Auto);
Console.WriteLine(clientNoSSL.IsConnected.ToString());
clientNoSSL.Authenticate(obj.user, obj.password);
if (clientNoSSL.IsAuthenticated == true)
{
for (int i = 0; i < clientNoSSL.Count; i++)
{
var message = clientNoSSL.GetMessage(i);
Console.WriteLine(message.From.ToString());
}
}
else
{
Console.WriteLine("No");
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
正如@jdweng 在评论中提到的,您需要做的是:
public void connect()
{
foreach (ObjectDeserializer obj in mailDeserialization.ListOfObjects())
{
Console.WriteLine(obj.toString());
using (var client = new Pop3Client ())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.CheckCertificateRevocation = false;
try {
client.Connect(obj.server, obj.port, SecureSocketOptions.Auto);
client.Authenticate(obj.user, obj.password);
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
Console.WriteLine(message.From.ToString());
}
client.Disconnect (true);
} catch (Exception ex) {
Console.WriteLine (ex);
if (client.IsConnected)
client.Disconnect (false);
}
}
}
}
我还冒昧地简化了您的代码,不再需要 if/else 检查端口的逻辑,原因有两个:
- 由于您使用
Auto
作为 SSL 模式,这意味着如果服务器支持,MailKit 将在连接到纯文本端口后尝试升级到 SSL/TLS 连接STARTTLS
(或 POP3 中的 STLS
)命令,这意味着可能需要验证回调和证书吊销属性 。
- 即使不需要它们,也不会中断纯文本连接,因为不会使用这些属性。
我应该警告说使用 client.ServerCertificateValidationCallback = (s, c, h, e) => true;
是不安全的并且会允许 MITM 攻击。我曾经在我的 README 中有过这种破解,因为开发人员 运行 他们在 Linux 上的 Mono 代码,例如,他们的 SSL 证书数据库中通常没有任何根 CA 证书,因此他们建立的每个 SSL 连接会因为无法验证任何 SSL 证书而失败。另一个原因是因为自签名 SSL 证书在家庭邮件服务器上非常普遍。
从 MailKit 2.6.0 开始,MailKit 有一个默认的 ServerCertificateValidationCallback 实现,它已经知道最常见的 IMAP、SMTP 和 POP3 邮件服务器的指纹和其他识别信息,因此在大多数情况下不再需要 hack。
我正在使用 mailkit 访问 pop3clients 列表。出于测试目的,我有一个不会进行身份验证的客户端,我写了一个 if 语句来进行身份验证 true 来完成一些任务。但是它没有移动到另一个客户端,而是抛出异常并停止进程。我应该实现什么或添加到我的代码中以便能够在没有连接或身份验证的情况下移动到另一个客户端。
public void connect(){
try
{
foreach (ObjectDeserializer obj in mailDeserialization.ListOfObjects())
{
Console.WriteLine(obj.toString());
if (obj.port == 995)
{
using (Pop3Client client = new Pop3Client())
{
client.CheckCertificateRevocation = false;
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect(obj.server, obj.port, SecureSocketOptions.Auto);
client.Authenticate(obj.user, obj.password);
if (client.IsAuthenticated == true)
{
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
Console.WriteLine(message.From.ToString());
}
}
}
}
else
{
using (Pop3Client clientNoSSL = new Pop3Client(new ProtocolLogger("pop3.log")))
{
clientNoSSL.Connect(obj.server, obj.port, SecureSocketOptions.Auto);
Console.WriteLine(clientNoSSL.IsConnected.ToString());
clientNoSSL.Authenticate(obj.user, obj.password);
if (clientNoSSL.IsAuthenticated == true)
{
for (int i = 0; i < clientNoSSL.Count; i++)
{
var message = clientNoSSL.GetMessage(i);
Console.WriteLine(message.From.ToString());
}
}
else
{
Console.WriteLine("No");
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
正如@jdweng 在评论中提到的,您需要做的是:
public void connect()
{
foreach (ObjectDeserializer obj in mailDeserialization.ListOfObjects())
{
Console.WriteLine(obj.toString());
using (var client = new Pop3Client ())
{
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.CheckCertificateRevocation = false;
try {
client.Connect(obj.server, obj.port, SecureSocketOptions.Auto);
client.Authenticate(obj.user, obj.password);
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
Console.WriteLine(message.From.ToString());
}
client.Disconnect (true);
} catch (Exception ex) {
Console.WriteLine (ex);
if (client.IsConnected)
client.Disconnect (false);
}
}
}
}
我还冒昧地简化了您的代码,不再需要 if/else 检查端口的逻辑,原因有两个:
- 由于您使用
Auto
作为 SSL 模式,这意味着如果服务器支持,MailKit 将在连接到纯文本端口后尝试升级到 SSL/TLS 连接STARTTLS
(或 POP3 中的STLS
)命令,这意味着可能需要验证回调和证书吊销属性 。 - 即使不需要它们,也不会中断纯文本连接,因为不会使用这些属性。
我应该警告说使用 client.ServerCertificateValidationCallback = (s, c, h, e) => true;
是不安全的并且会允许 MITM 攻击。我曾经在我的 README 中有过这种破解,因为开发人员 运行 他们在 Linux 上的 Mono 代码,例如,他们的 SSL 证书数据库中通常没有任何根 CA 证书,因此他们建立的每个 SSL 连接会因为无法验证任何 SSL 证书而失败。另一个原因是因为自签名 SSL 证书在家庭邮件服务器上非常普遍。
从 MailKit 2.6.0 开始,MailKit 有一个默认的 ServerCertificateValidationCallback 实现,它已经知道最常见的 IMAP、SMTP 和 POP3 邮件服务器的指纹和其他识别信息,因此在大多数情况下不再需要 hack。