.Net邮件客户端对接Office 365账户OAuth2授权异常求助
问题
我正在为应用集成SMTP服务,无Azure使用经验。客户使用不同邮件提供商,可自行配置账户。目前用MailKit对接微软账户(个人及企业版)时遇到问题:已在Microsoft Entra创建支持多租户及个人微软账户的应用,内部组织账户可正常使用,但外部微软账户调用时返回AADSTS50034错误。
测试代码
using MailKit.Net.Smtp; using MailKit.Security; using MimeKit; using Newtonsoft.Json.Linq; namespace MailKitTest { public class EmailTest { private SmtpClient smtpClient; static async Task<SaslMechanismOAuth2> GetAccessToken(string api_perm) { var content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("scope", api_perm), new KeyValuePair<string, string>("grant_type", "password"), new KeyValuePair<string, string>("resource", "https://outlook.office365.com/"), new KeyValuePair<string, string>("client_id", "<client_id>"), new KeyValuePair<string, string>("client_secret", "<client_secret>"), new KeyValuePair<string, string>("username", "<test@live.com>"), new KeyValuePair<string, string>("password", "<user_password") }); var client = new HttpClient(); var response = await client.PostAsync($"https://login.microsoftonline.com/common/oauth2/token", content).ConfigureAwait(continueOnCapturedContext: false); //nosas contas, versão 1 var jsonString = await response.Content.ReadAsStringAsync(); var jobj = JObject.Parse(jsonString); var token = jobj["access_token"]; client.Dispose(); return new SaslMechanismOAuth2("<test@live.com>", token.ToString()); } void sendMail() { smtpClient.Authenticated += Client_Authenticated; using (smtpClient) { smtpClient.Connect("smtp.office365.com", 587, SecureSocketOptions.Auto); if (smtpClient.AuthenticationMechanisms.Contains("OAUTHBEARER") || smtpClient.AuthenticationMechanisms.Contains("XOAUTH2")) { SaslMechanismOAuth2 at = GetAccessToken("SMTP.Send").Result; smtpClient.Authenticate(at); } } } private void Client_Authenticated(object? sender, MailKit.AuthenticatedEventArgs e) { MimeMessage msg = new MimeMessage(); msg.From.Add(MailboxAddress.Parse("<test@live.com>")); msg.To.Add(InternetAddress.Parse("<another_email@test.com>")); msg.Subject = "OAUTH Test"; msg.Body = new TextPart("plain") { Text = "OAUTH Test " + DateTime.Now.ToLongTimeString() }; smtpClient.Send(msg); smtpClient.Disconnect(true); } } }
应用配置
- 认证类型:移动和桌面应用
- 支持范围:多租户及个人微软账户
- 已配置权限并创建客户端密钥
错误信息
{ "correlation_id": "6a4b9d97-b92d-4552-84d2-e1d4c80b61b8", "error": "invalid_grant", "error_codes": [ 50034 ], "error_description": "AADSTS50034: The user account {EUII Hidden} does not exist in the hotmail.com directory. To sign into this application, the account must be added to the directory. Trace ID: ba97f9bb-5b07-40b2-8a83-aefdcd8d1900 Correlation ID: 6a4b9d97-b92d-4552-84d2-e1d4c80b61b8 Timestamp: 2024-07-18 11:52:17Z", "error_uri": "https://login.microsoftonline.com/error?code=50034", "timestamp": "2024-07-18 11:52:17Z", "trace_id": "ba97f9bb-5b07-40b2-8a83-aefdcd8d1900" }
咨询:如何让该SMTP客户端(Entra应用)支持所有微软账户使用?
解决方案
1. 替换授权流:密码流不支持个人微软账户
你当前用的password授权类型(资源所有者密码凭证流)只适用于Azure AD组织账户,个人微软账户(live.com/hotmail.com等)完全不支持这个流,这就是AADSTS50034错误的核心原因。
必须改用授权码流(Authorization Code Flow),这是微软官方推荐的桌面/移动应用OAuth2授权方式,能覆盖所有类型的微软账户。
2. 调整应用权限配置
- 确保在Entra应用中添加的是Delegated权限,SMTP.Send只支持Delegated类型,不要选Application权限。
- 权限范围指定为
https://outlook.office365.com/SMTP.Send,企业账户需要管理员同意,个人账户由用户自己授权即可。
3. 代码修改要点
- 删除原有的密码流获取token逻辑,改成引导用户跳转到微软授权页面获取授权码,再用授权码兑换access token。
- 桌面应用可以用本地端口监听回调(比如
http://localhost:8080)来接收授权码。 - 获取到token后,SMTP的OAuth2认证逻辑和原代码一致,直接用
SaslMechanismOAuth2对象传入token即可。
4. 其他关键设置
- 确认Entra应用的"支持的账户类型"设置为**"任何组织目录中的账户和个人微软账户(例如Skype、Xbox)"**,这个配置不能错。
- 个人微软账户无需开启"不太安全的应用访问",OAuth2方式本身就是安全授权。
内容的提问来源于stack exchange,提问作者MSantos
相关产品推荐
相关产品推荐

