为了更好地保护您的用户,GMail和其他邮件Provider 建议将我们的所有应用程序升级到OAuth 2.0.

这意味着System.Net.Mail不能再工作了,我们需要使用另一个像MailKit这样的库,我说的对吗?

总的来说,我试图理解如何在不允许"访问不太安全的应用程序"的情况下发送邮箱?

因为我被处决时有System.Net.Mail.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required.人.

如果解决这个问题的唯一方法是使用MailKit,我认为这个问题将是一个很好的实用的逐步切换教程,从System.Net.Mail切换到使用MailKitGoogle.Apis.Auth.OAuth2.我不知道通用解决方案是否会使用DotNetOpenAuth

我的应用程序中有以下类,它们对应于向任何地址(gmail、yandex和其他地址)发送邮箱:

public class EmailSender
{
    public void SendEmail(SmtpServerSettings serverSettings, SendEmailRequest emailRequest)
    {
        // Usually I have 587 port, SmtpServerName = smtp.gmail.com 
        _logger.Trace("Sending message with subject '{0}' using SMTP server {1}:{2}",
                      emailRequest.Subject,
                      serverSettings.SmtpServerName,
                      serverSettings.SmtpPort);

        try
        {
            using (var smtpClient = new SmtpClient(serverSettings.SmtpServerName, (int)serverSettings.SmtpPort))
            {
                smtpClient.EnableSsl = serverSettings.SmtpUseSsl; // true
                if (!string.IsNullOrEmpty(serverSettings.UserName) || !string.IsNullOrEmpty(serverSettings.EncryptedPassword))
                {
                    smtpClient.Credentials = new NetworkCredential(serverSettings.UserName, serverSettings.EncryptedPassword);
                }

                smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
                smtpClient.Timeout = (int)serverSettings.SmtpTimeout.TotalMilliseconds;

                using (var message = new MailMessage())
                {
                    message.From = new MailAddress(serverSettings.FromAddress);

                    emailRequest.To.ForEach(message.To.Add);
                    emailRequest.CC.ForEach(message.CC.Add);
                    emailRequest.Bcc.ForEach(message.Bcc.Add);

                    message.Subject = emailRequest.Subject.Replace('\r', ' ').Replace('\n', ' ');
                    message.Body = emailRequest.Body;
                    message.BodyEncoding = Encoding.UTF8;
                    message.IsBodyHtml = false;

                    smtpClient.Send(message);
                }
            }

            _logger.Trace("Sent message with subject '{0}' using SMTP server {1}:{2}",
                          emailRequest.Subject,
                          serverSettings.SmtpServerName,
                          serverSettings.SmtpPort);
        }
        catch (SmtpFailedRecipientsException e)
        {
            var failedRecipients = e.InnerExceptions.Select(x => x.FailedRecipient);
            LogAndReThrowWithValidMessage(e, EmailsLocalization.EmailDeliveryFailed, failedRecipients);
        }
   }
}

它在new Google security policies号之前工作得很好.

我知道System.Net.Mail不支持OAuth2.我决定用MailKit's SmtpClient来发送信息.

经过调查,我知道我的初始代码没有太大变化,因为MailKit's API看起来非常相似(System.Net.Mail).

除了一个细节:我需要用户的OAuth访问令牌(MailKit没有获取OAuth令牌的代码,但如果我有,它可以使用它).

因此,在future 我将有以下几行:

smtpClient.Authenticate (usersLoginName, usersOAuthToken);

我想在SendEmail方法中添加GoogleCredentials作为新参数:

public void SendEmail(SmtpServerSettings serverSettings, SendEmailRequest emailRequest, 
                      GoogleCredentials credentials)
{
    var certificate = new X509Certificate2(credentials.CertificateFilePath,
                                           credentials.PrivateKey,
                                           X509KeyStorageFlags.Exportable);

     var credential = new ServiceAccountCredential(
                      new ServiceAccountCredential.Initializer(credentials.ServiceAccountEmail)
                             {
                                 Scopes = new[] { "https://mail.google.com/" },
                                 User = serverSettings.UserName
                             }.FromCertificate(certificate));

    ....
    //my previous code but with MailKit API
}

如何获得usersOAuthToken分?

我上面发布的代码只适用于GMail,不适用于yandex.ru或其他邮件Provider .为了与他人合作,我可能需要使用另一个OAuth2库.但我不想在我的代码中为许多可能的邮件Provider 提供许多身份验证机制.我想 for each 邮件Provider 提供一个通用解决方案.还有一个可以发送邮箱的库(比如.net smtpclient)

推荐答案

一般的解决方案是https://galleryserverpro.com/use-gmail-as-your-smtp-server-even-when-using-2-factor-authentication-2-step-verification/

1)使用浏览器登录您的Google帐户,然后转到您的登录&;安全设置.查找两步验证设置.

2) 如果关闭了两步验证,并且您希望保持这种状态,这意味着您将需要实现许多验证机制,正如您所说的.

解决方案:打开它,然后生成并使用谷歌应用程序密码.应该有用!你不需要使用其他库,比如mailkit.

.net相关问答推荐

Azure管道-使用.NET 8 RC2 SDK生成C#项目失败

NuGet 兼容与计算框架(Xamarin 和 .NET 6)

C#.Net 中的可选返回

代理、包装器或外观类之间有什么区别

.NET 应用程序的链接器状态(又名请先生,我可以有一个链接器2009 年版)

SubscribeOn 和 ObserveOn 有什么区别

String 是原始类型吗?

DBNull 的意义何在?

什么是 Hashtable 的通用版本?

从 Windows 窗体打开 URL

所有数组在 C# 中都实现了哪些接口?

在生产环境中部署调试符号(pdb 文件)有什么风险?

将记录器作为单身人士是一个好习惯吗?

用 double 替换 int 时的 Visual Studio 长编译

.NET 配置文件 configSource 在应用程序目录文件夹之外

接口属性的 XML 序列化

泛型类的默认构造函数的语法是什么?

WPF 中的 Application.DoEvents() 在哪里?

检测到包降级警告(dotnet core,vs 2017)

通过反射获取公共静态字段的值