C#:正确地以安全的方式发送电子邮件

时间:2010-06-09 21:37:59

标签: c# validation email ssl ssl-certificate

尝试使用C#发送安全电子邮件,并想知道我是否理解正确。我目前有以下计划:

using System;
using System.Net.Mail;
using System.Net;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Net.Security;

namespace Geekality.SecureEmail
{
    class Program
    {
        static bool OurCertificateValidation(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            var actualCertificate = X509Certificate.CreateFromCertFile("example.com.cert");

            return certificate.Equals(actualCertificate);
        }

        static void Main(string[] args)
        {
            // Register our own certificate validation
            ServicePointManager.ServerCertificateValidationCallback = OurCertificateValidation;

            // Message
            var from = new MailAddress("me@example.com", "Me");
            var to = new MailAddress("you@example.com", "Myself");

            var message = new MailMessage(from, to)
            {
                Subject = "Greetings!",
                Body = "How are you doing today?",
            };

            // Create client
            var client = new SmtpClient("smtp.example.com")
            {
                EnableSsl = true,
                Credentials = new NetworkCredential
                {
                    UserName = "me@example.com",
                    Password = "password",
                },
            };

            // Try to send
            using (client)
            {
                try
                {
                    client.Send(message);
                    Console.WriteLine("Message sent!");
                }
                catch (AuthenticationException e)
                {
                    Console.WriteLine("Authentication failed:");
                    Console.WriteLine(e.Message);
                }
                catch (SmtpException e)
                {
                    Console.WriteLine("SMTP error:");
                    Console.WriteLine(e.Message);
                }
            }

            Console.ReadKey(true);
        }
    }
}

但数据当然已更改为示例值。无论如何,这似乎从我能看到的很好。对我所做的任何评论?特别是关于我如何进行证书验证的问题。这是一个很好的方式吗?或者我在这里错过了一些如此糟糕的事情,以至于我不得不发送不使用SSL的电子邮件?

我自己进行验证的原因是默认验证失败,因为它是自行颁发的证书,而我使用的邮件域与使用的证书中的邮件域不同。我正在使用 mail.mydomain.com ,而证书中的域名类似于 mywebhost.com 。所以我所做的是使用它的邮件客户端从Opera获取证书文件并存储它,以便我可以将它与我在尝试发送电子邮件时获得的文件进行比较。这是一种安全且好的方法来进行此验证吗?我也知道实际证书的哈希,并试图用它来与我在发送电子邮件时得到的那个进行比较。这也很有用,虽然在代码行中它几乎是一样的。只是与字符串而不是文件进行比较。这些方法中的任何一种都比其他方式更好吗?

2 个答案:

答案 0 :(得分:0)

您的代码只是一个附带问题 - 为什么要将参数object sX509Chain chainSslPolicyErrors sslPolicyErrors传递到您的OurCertificateValidation方法中?它们没有被引用。

答案 1 :(得分:0)

您没有检查证书有效期,也没有检查服务器是否已撤销它。一般来说,正确的证书验证是非常重要的事情。

有效期检查很简单 - 只需检查证书的ValidFrom和ValidTo属性即可。验证的时刻必须介于两者之间。至于撤销检查, - 如果您还有自签名证书,服务器维护人员很可能会费心管理CRL或安装OCSP服务器进行在线验证。因此,您可以在特定情况下跳过此步骤

最后,如果服务器将证书更改为另一个合法的证书怎么办?您将需要更改您的代码(或带有证书的文件),不是吗?