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

微软禁用旧SMTP后,C# Windows Service邮件发送的简便替代方案

最优方案:SMTP + OAuth 2.0 密码授权流(Password Grant Flow)

针对你的场景——无交互Windows Service、仅持有用户邮箱密码、对接IT能力有限的小企业,SMTP结合OAuth 2.0密码授权流是最接近旧SMTP模式的重构方案,无需复杂的Azure应用注册或用户交互,配置和代码改动最小。

核心优势

  • 完全沿用你熟悉的SMTP发送逻辑,仅替换身份验证方式
  • 仅需用户邮箱、密码,无需额外Azure配置(仅需租户端做1次极简权限开启)
  • 适配无交互服务场景,不需要用户登录授权

实现步骤

1. 租户端极简配置(小企业IT仅需操作1次)

默认部分Office 365租户可能禁用密码授权流,需要租户管理员完成:

  • 登录Azure AD门户,找到对应用户账号,确保允许使用旧版身份验证(若租户全局禁用,需全局开启;仅针对用户则开启用户级旧版验证)
  • 确认用户拥有Exchange Online许可证(发送邮件必备)

2. 代码实现(基于MailKit + MSAL)

安装依赖NuGet包

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

核心代码示例

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

public class Office365SmtpOAuthSender
{
    private const string SmtpServer = "smtp.office365.com";
    private const int SmtpPort = 587;
    private const string TenantId = "common"; // Office 365全局租户直接用"common"
    // 微软官方公共客户端ID,无需自行注册Azure应用
    private const string ClientId = "d3590ed6-52b3-4102-aeff-aad2292ab01c";

    public async Task SendEmailAsync(string username, string password, string toEmail, string subject, string body)
    {
        // 获取OAuth 2.0令牌
        var token = await GetOAuthTokenAsync(username, password);

        // 构建邮件(和旧SMTP逻辑完全一致)
        var message = new MimeMessage();
        message.From.Add(new MailboxAddress("发送人", username));
        message.To.Add(new MailboxAddress("收件人", toEmail));
        message.Subject = subject;
        message.Body = new TextPart("html") { Text = body };

        // SMTP发送(仅认证方式替换为OAuth2)
        using var client = new SmtpClient();
        await client.ConnectAsync(SmtpServer, SmtpPort, SecureSocketOptions.StartTls);
        
        // 应用OAuth2认证
        await client.AuthenticateAsync(new SaslMechanismOAuth2(username, token));
        
        await client.SendAsync(message);
        await client.DisconnectAsync(true);
    }

    private async Task<string> GetOAuthTokenAsync(string username, string password)
    {
        var app = PublicClientApplicationBuilder
            .Create(ClientId)
            .WithAuthority($"https://login.microsoftonline.com/{TenantId}")
            .Build();

        // SMTP发送专用权限范围
        var scopes = new[] { "https://outlook.office365.com/SMTP.Send" };
        
        // 密码授权流获取令牌
        var result = await app.AcquireTokenByUsernamePassword(scopes, username, password)
            .ExecuteAsync();

        return result.AccessToken;
    }
}

关键说明

  • 使用微软官方提供的公共客户端ID,无需自行注册Azure应用,彻底简化配置
  • 令牌请求的SMTP.Send作用域专门对应SMTP发送权限,精准匹配需求
  • 代码逻辑和旧SMTP发送几乎一致,仅新增令牌获取和OAuth认证两个步骤

注意事项

  1. 安全要求:禁止硬编码用户密码,建议用Windows服务加密配置文件或Windows凭据管理器存储密码
  2. 微软限制:密码授权流属于微软"不推荐但仍支持"的遗留场景,当前是适配你需求的最优解,若未来有变更可再迁移
  3. 故障排查:若获取令牌失败,检查租户旧版验证是否开启、用户密码是否正确、是否有Exchange Online许可证

为什么不选其他方案?

  • Graph API发送邮件:需要注册Azure应用、配置应用权限、获取客户端凭据,步骤繁琐,且完全脱离SMTP逻辑,改动量大
  • 客户端凭据流:需要Azure应用注册、全局管理员授权,不适合IT能力弱的小企业,且无法代表特定用户发送邮件(只能用应用身份)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 06:55:21