使用 MailKit 和 ASP.NET Core Web API 修复 Outlook 中的简单身份验证问题

OAuth2

了解 ASP.NET Core 和 MailKit 的 Outlook 身份验证问题

将 Outlook 电子邮件功能集成到 使用 MailKit 时,开发人员经常会遇到身份验证问题。一种常见问题是“535:5.7.139 身份验证失败”错误消息。当 Outlook 服务器上禁用基本身份验证方法时,通常会发生这种情况,导致连接尝试失败。

曾经广泛使用的基本身份验证已越来越多地被 Microsoft 等服务提供商禁用,以增强安全性。相反,现代身份验证方法(例如 OAuth2)是首选。这种转变可能会导致混乱,特别是对于习惯直接使用用户名和密码的开发人员而言。

在这种情况下,您可能使用了正确的 Outlook SMTP 服务器设置和应用程序专用密码,但仍然面临身份验证错误。了解基本身份验证失败的原因对于有效解决这些问题至关重要。该错误表明安全策略强制执行,而不是代码本身存在问题。

在本文中,我们将探讨发生此错误的原因、根本原因以及解决该问题可以采取的步骤。我们还将讨论替代身份验证方法,例如 OAuth2,以确保与 Outlook 服务器的安全和成功通信。

命令 使用示例
ConfidentialClientApplicationBuilder.Create() 此命令用于构建用于 OAuth2 身份验证的机密客户端应用程序。它是 Microsoft 身份客户端 (MSAL) 库的一部分,并使用客户端 ID 初始化应用程序,使其能够获取用于安全通信的令牌。
SaslMechanismOAuth2() 此命令特定于 MailKit,用于在发送电子邮件时使用 OAuth2 令牌进行身份验证。它通过 OAuth2 协议使用更安全的方法来绕过基本身份验证。
AcquireTokenForClient(scopes).ExecuteAsync() 此方法获取客户端应用程序的 OAuth2 令牌。它是 MSAL 库的一部分,对于为 Microsoft Graph 或 SMTP 服务器等 API 生成访问令牌至关重要。
GraphServiceClient 该对象在 Microsoft Graph API 中用于与 Microsoft 服务交互。它允许开发人员使用 OAuth2 令牌发送电子邮件、管理用户或与 Microsoft 365 中的其他资源进行交互。
DelegateAuthenticationProvider() 此命令用于设置 Microsoft Graph API 请求的身份验证过程。它为每个 API 请求动态分配 OAuth2 令牌,确保安全通信。
SendMail(message, false).Request().PostAsync() 此命令是 Graph API 的一部分,用于异步发送构造的电子邮件消息。它使用 Microsoft Graph 的安全电子邮件发送功能将消息发布到用户的邮箱。
SmtpClient.AuthenticateAsync() 在 MailKit 中,此命令允许客户端使用 OAuth2 令牌等凭据向电子邮件服务器进行身份验证。它取代了传统的用户名和密码身份验证方法。
SecureSocketOptions.StartTls 连接到 SMTP 服务器时使用此命令,通过 STARTTLS 协议强制实施安全、加密的连接,确保数据通过网络安全传输。
MimeMessage 此类代表 MailKit 库中的电子邮件消息。它包含电子邮件的发件人、收件人、主题和正文等详细信息。在发送之前创建和格式化电子邮件内容至关重要。

探索 OAuth2 集成以实现安全电子邮件发送

上面提供的脚本旨在解决 在 ASP.NET Core Web API 中使用 MailKit 通过 Outlook 的 SMTP 服务器发送电子邮件时遇到。发生该错误的原因是 Microsoft 禁用了基本身份验证以增强安全性,迫使开发人员采用更安全的身份验证方法 OAuth2。在第一个解决方案中,我们使用 MailKit 和 OAuth2 令牌来进行身份验证和发送电子邮件。 OAuth2 不依赖用户名和密码,而是需要一个令牌,该令牌由 Microsoft 身份客户端 (MSAL) 生成,用于安全地验证请求。

首先,该解决方案使用“ConfidentialClientApplicationBuilder.Create()”方法(MSAL 库的一部分)来创建客户端应用程序。此步骤使用生成 OAuth2 令牌所需的基本凭据(例如客户端 ID、租户 ID 和客户端密钥)初始化应用程序。构建应用程序后,“AcquireTokenForClient()”方法将检索通过 Outlook 的 SMTP 服务器进行身份验证所需的令牌。通过使用 SaslMechanismOAuth2() 机制,MailKit 可以使用此令牌对电子邮件发送过程进行身份验证,完全绕过基本身份验证。此方法可确保应用程序遵守现代安全协议并避免弃用的方法。

在第二种解决方案中,Microsoft Graph API 用于发送电子邮件,而不直接与 SMTP 服务器交互。 Microsoft Graph 提供了用于管理 Microsoft 服务(包括 Outlook 电子邮件)的一体化解决方案。 Graph API 通过“DelegateAuthenticationProvider()”利用 OAuth2 身份验证,为每个请求分配一个 OAuth2 令牌。此令牌是使用 MSAL 类似地生成的。 “GraphServiceClient”对象促进与 Microsoft 服务器的安全通信,允许 API 无缝发送电子邮件。对于那些想要处理更广泛的 Microsoft 服务、减少与 SMTP 等单个服务的直接连接的用户来说,此方法特别有用。

最后,在第三个解决方案中,我们探索了一种更传统的方法,使用内置的 .NET 的命名空间。虽然它仍然使用 OAuth2 进行身份验证,但此方法用 System.Net.Mail 的 SMTP 客户端替换 MailKit 来发送电子邮件。 OAuth2 令牌作为凭证而不是通常的用户名和密码组合传入。电子邮件是使用典型的“MailMessage”和“SmtpClient”对象构建和发送的。对于喜欢使用本机 .NET 库但仍需要安全 OAuth2 身份验证来发送电子邮件的开发人员来说,此方法非常有用。

所有这些方法不仅解决了基本身份验证被禁用的问题,而且还使 ASP.NET Core Web API 中的电子邮件发送功能面向未来。每个解决方案都强调了通过 OAuth2 实现安全性的重要性,取代了过时且安全性较低的身份验证方法。通过利用 MSAL 和 Microsoft Graph 等现代身份验证库,开发人员可以确保其应用程序始终符合最新的安全标准,同时仍然提供可靠的电子邮件发送功能。

解决方案 1:切换到 OAuth2 进行 Outlook 身份验证

此方法使用 ASP.NET Core 和 MailKit,用 OAuth2 替换基本身份验证,这是在 Outlook 中安全发送电子邮件的推荐方法。

// Step 1: Install required NuGet packages
// MailKit, MimeKit, and Microsoft.Identity.Client for OAuth2

using MailKit.Net.Smtp;
using MimeKit;
using Microsoft.Identity.Client;

// Step 2: Configure OAuth2 authentication
var clientId = "your-client-id";
var tenantId = "your-tenant-id";
var clientSecret = "your-client-secret";

var cca = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithClientSecret(clientSecret)
    .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
    .Build();

var scopes = new[] { "https://outlook.office365.com/.default" };
var result = await cca.AcquireTokenForClient(scopes).ExecuteAsync();

// Step 3: Send email using OAuth2 token
var emailMessage = new MimeMessage();
emailMessage.From.Add(new MailboxAddress("Your Name", "your-email@outlook.com"));
emailMessage.To.Add(new MailboxAddress("Recipient", "recipient@example.com"));
emailMessage.Subject = "Subject";
emailMessage.Body = new TextPart("plain") { Text = "Hello, this is a test email." };

using (var smtpClient = new SmtpClient())
{
    await smtpClient.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
    await smtpClient.AuthenticateAsync(new SaslMechanismOAuth2("your-email@outlook.com", result.AccessToken));
    await smtpClient.SendAsync(emailMessage);
    await smtpClient.DisconnectAsync(true);
}

解决方案 2:使用 Microsoft Graph API 发送电子邮件

此方法涉及使用 Microsoft Graph API 从 ASP.NET Core 后端发送电子邮件,完全绕过 SMTP 配置。

// Step 1: Add Microsoft.Graph NuGet package
using Microsoft.Graph;
using Microsoft.Identity.Client;

// Step 2: Configure Graph API and authentication
var confidentialClient = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithTenantId(tenantId)
    .WithClientSecret(clientSecret)
    .Build();

var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
    var authResult = await confidentialClient.AcquireTokenForClient(scopes).ExecuteAsync();
    requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
}));

// Step 3: Prepare and send email via Graph API
var message = new Message
{
    Subject = "Test Email",
    Body = new ItemBody
    {
        ContentType = BodyType.Text,
        Content = "Hello, this is a test email sent via Microsoft Graph API."
    },
    ToRecipients = new List<Recipient>()
    {
        new Recipient { EmailAddress = new EmailAddress { Address = "recipient@example.com" } }
    }
};

await graphClient.Users["your-email@outlook.com"].SendMail(message, false).Request().PostAsync();

解决方案 3:将 OAuth2 与 SMTP 结合使用(不同的库)

此方法使用 System.Net.Mail 通过 OAuth2(而不是 MailKit)发送电子邮件,并具有相同的 OAuth 身份验证方法。

// Step 1: Configure OAuth2 with System.Net.Mail
var smtpClient = new SmtpClient("smtp.office365.com")
{
    Port = 587,
    EnableSsl = true,
    UseDefaultCredentials = false,
    Credentials = new NetworkCredential("your-email@outlook.com", accessToken)
};

// Step 2: Construct the email message
var mailMessage = new MailMessage
{
    From = new MailAddress("your-email@outlook.com"),
    Subject = "Test Email",
    Body = "This is a test email sent using System.Net.Mail with OAuth2.",
    IsBodyHtml = true
};

mailMessage.To.Add("recipient@example.com");

// Step 3: Send the email
await smtpClient.SendMailAsync(mailMessage);

实施电子邮件发送的现代安全标准

在现代电子邮件系统的背景下,基本身份验证越来越被视为过时且不安全。对于 Outlook 等主要服务提供商来说尤其如此,它们已禁用基本身份验证以实施 OAuth2 等更安全的机制。基本身份验证仅依赖于用户名和密码,很容易受到暴力攻击,并且如果凭据被盗,则可能会受到损害。因此,正如 Microsoft 所鼓励的那样,转向 OAuth2 可确保安全地交换令牌,而不会暴露用户凭据。

实施 OAuth2 的一个重要方面是访问令牌的概念。 OAuth2 不依赖通过 SMTP 服务器的直接身份验证,而是颁发有时限的令牌,允许安全访问电子邮件服务等资源。这些令牌由授权服务器授予,开发人员可以使用 Microsoft Identity Client (MSAL) 等库获取它们。通过这些令牌,应用程序可以获得对用户帐户的有限访问权限,从而降低与长期静态凭证相关的风险。

此外,采用 OAuth2 不仅可以使您的应用程序与现代安全实践保持一致,还可以为未来的发展做好准备。许多 API(包括基于云的服务的 API)现在严重依赖 OAuth2 来实现安全通信。这可以确保电子邮件发送功能随着服务的发展而保持功能和安全。对于开发人员集成 和 ,利用 OAuth2 带来了一系列安全增强功能,从基于令牌的身份验证到通过 STARTTLS 等协议的加密传输。

  1. Outlook 中出现 535: 5.7.139 错误的原因是什么?
  2. 出现此错误的原因是 Outlook 的 SMTP 服务器禁用了基本身份验证。 Microsoft 现在需要 OAuth2 进行安全身份验证。
  3. 如何在 MailKit 中启用 OAuth2?
  4. 您可以使用以下方式实现 OAuth2 配置您的应用程序并 使用令牌验证电子邮件发送。
  5. 在 Outlook 中发送电子邮件的基本身份验证的替代方法是什么?
  6. OAuth2 是首选替代方案。它使用令牌而不是用户名和密码来进行安全、有时间限制的身份验证。
  7. Microsoft Graph API 是否比使用 SMTP 发送电子邮件更好?
  8. Microsoft Graph API 是一项更广泛的服务,可以处理的不仅仅是发送电子邮件。如果您需要访问各种 Microsoft 365 资源,它的用途更加广泛,建议您使用它。
  9. 如何测试 OAuth2 在我的应用程序中是否正常工作?
  10. 您可以实施单元测试来验证您的 OAuth2 令牌是否正在生成并正确传递到电子邮件发送服务。

解决 Outlook 中的基本身份验证错误需要采用 OAuth2 等现代安全标准。这种方法消除了基本身份验证的漏洞,并提供了一种通过 Outlook 的 SMTP 服务器发送邮件的更安全的方法。

通过将 OAuth2 与 ASP.NET Core 和 MailKit 集成,开发人员可以确保其应用程序面向未来,确保安全通信并符合更新的服务提供商要求。这不仅解决了身份验证问题,还增强了整体安全性和功能。

  1. 有关 Microsoft 弃用基本身份验证和 OAuth2 实施的详细文档: Microsoft Exchange Online 基本身份验证弃用
  2. 有关在 .NET 中使用 MailKit 和 MimeKit 实现电子邮件功能的综合指南: MailKit 文档
  3. 用于 OAuth2 身份验证的 MSAL(Microsoft 身份客户端)库文档: Microsoft 身份平台 (MSAL) 概述