You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core应用中如何使用MailKit保持与Office365的连接,避免每次发送邮件时重复用户认证

解决方案:ASP.NET Core + MailKit 安全对接 Office 365 发送邮件

针对你的场景,我推荐采用Azure AD OAuth2.0 认证结合 MailKit的方案,这是符合安全最佳实践且适配你组织统一身份体系的最优解。先帮你分析下之前的几个方案问题,再详细讲正确的实现方式:

先排除不可行的方案

  • 方案1:用SMTP认证做应用登录:不可行。SMTP的Authenticate是专门用于邮件发送的一次性认证,Office 365的SMTP连接闲置1小时左右就会断开,无法用来维持应用会话;而且SMTP协议并非为用户身份验证设计,没法生成应用所需的会话令牌,不符合登录流程的最佳实践。
  • 方案2:会话存储加密密码:严重不推荐。无论加密方式多复杂,存储用户密码(哪怕是加密后的)都存在泄露风险,而且你组织的密码定期更新,会话中的密码很快会失效,还得重新输入,完全不符合自动化需求。

最优方案:Azure AD OAuth2.0 认证

你提到的方案3是正确的方向,结合你组织的Windows统一身份体系,可以实现无密码的自动认证,无需硬编码邮箱账号密码。以下分两种场景详细说明:

场景1:代表登录用户发送邮件(用户身份)

适合用户在应用内操作后,以自己的Office 365邮箱发送邮件的场景,利用组织的Windows集成认证自动获取令牌,无需用户输入密码。

步骤1:Azure AD 注册应用(需管理员审批)

  1. 在Azure AD中注册一个单租户应用(仅限你组织内部使用)。
  2. 为应用添加委派权限(Delegated Permissions):搜索Office 365 Exchange Online,勾选SMTP.Send权限,提交后请管理员审批。
  3. 记录应用的Client ID和Tenant ID(后续代码要用)。

步骤2:ASP.NET Core 中实现令牌获取与邮件发送

使用Microsoft官方的Microsoft.Identity.Client(MSAL)库来管理令牌,它会自动缓存令牌并在过期前刷新,避免重复认证。

首先安装NuGet包:

Install-Package Microsoft.Identity.Client
Install-Package MailKit

然后编写令牌获取和邮件发送代码:

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

public class EmailService
{
    private readonly IConfiguration _configuration;

    public EmailService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    // 获取用户的OAuth2访问令牌(利用Windows集成认证)
    private async Task<string> GetUserOAuthTokenAsync(string userEmail)
    {
        var clientId = _configuration["AzureAd:ClientId"];
        var tenantId = _configuration["AzureAd:TenantId"];
        var authority = $"https://login.microsoftonline.com/{tenantId}";

        var publicClientApp = PublicClientApplicationBuilder
            .Create(clientId)
            .WithAuthority(authority)
            .Build();

        // 自动利用当前Windows登录身份获取令牌,无需用户输入密码
        var result = await publicClientApp.AcquireTokenByIntegratedWindowsAuth(
            new[] { "https://outlook.office365.com/SMTP.Send" })
            .WithUsername(userEmail)
            .ExecuteAsync();

        return result.AccessToken;
    }

    // 发送邮件(用OAuth2认证替代账号密码)
    public async Task SendEmailAsUserAsync(string userEmail, string recipient, string subject, string content)
    {
        var email = new MimeMessage();
        email.From.Add(MailboxAddress.Parse(userEmail));
        email.To.Add(MailboxAddress.Parse(recipient));
        email.Subject = subject;
        email.Body = new TextPart(TextFormat.Plain) { Text = content };

        using var smtp = new SmtpClient();
        await smtp.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
        
        // 使用OAuth2机制认证,无需硬编码密码
        await smtp.AuthenticateAsync(new SaslMechanismOAuth2(userEmail, await GetUserOAuthTokenAsync(userEmail)));
        
        await smtp.SendAsync(email);
        await smtp.DisconnectAsync(true);
    }
}

在appsettings.json中配置Azure AD参数:

{
  "AzureAd": {
    "ClientId": "你的应用Client ID",
    "TenantId": "你的组织租户ID"
  }
}

场景2:应用后台发送邮件(应用身份)

适合系统自动发送通知类邮件的场景,无需用户登录,用应用自身身份发送(需组织管理员授予应用级权限)。

步骤1:Azure AD 注册应用并配置权限

  1. 同样注册单租户应用,添加应用权限(Application Permissions):搜索Office 365 Exchange Online,勾选SMTP.Send.AsApp,提交后请全局管理员审批。
  2. 生成应用密钥(或使用证书更安全),记录Client ID、Tenant ID和Client Secret。

步骤2:实现应用令牌获取与邮件发送

private async Task<string> GetAppOAuthTokenAsync()
{
    var clientId = _configuration["AzureAd:ClientId"];
    var tenantId = _configuration["AzureAd:TenantId"];
    var clientSecret = _configuration["AzureAd:ClientSecret"];

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

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

    return result.AccessToken;
}

public async Task SendSystemEmailAsync(string recipient, string subject, string content)
{
    var serviceEmail = "你的组织服务邮箱@something.org";
    var email = new MimeMessage();
    email.From.Add(MailboxAddress.Parse(serviceEmail));
    email.To.Add(MailboxAddress.Parse(recipient));
    email.Subject = subject;
    email.Body = new TextPart(TextFormat.Plain) { Text = content };

    using var smtp = new SmtpClient();
    await smtp.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
    
    await smtp.AuthenticateAsync(new SaslMechanismOAuth2(serviceEmail, await GetAppOAuthTokenAsync()));
    
    await smtp.SendAsync(email);
    await smtp.DisconnectAsync(true);
}

关键优势与注意事项

  • 安全合规:完全避免硬编码密码,利用Azure AD的OAuth2机制认证,符合组织统一身份管理规则。
  • 自动化认证:结合Windows集成认证,用户无需手动输入Office 365密码;MSAL自动缓存令牌,过期自动刷新,无需每次发邮件都重新认证。
  • 敏感信息管理:Azure AD的Client ID、Tenant ID等敏感信息通过配置文件存储,生产环境建议用Azure Key Vault加密存储。

内容的提问来源于stack exchange,提问作者Qiuzman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:32:30