c# - 发送邮件时出现 EWS 和 OAuth 403 错误

标签 c# azure oauth azure-active-directory exchangewebservices

不久前,我用 C# 编写了一个简单的实用方法,由应用程序调用来自动发送电子邮件。

该应用程序用于通过基本身份验证(用户名+密码)在 EWS 中进行身份验证,一切正常。

从 2022 年 9 月开始,Microsoft 开始禁用这种现已弃用的身份验证方法,因此我决定使用 OAuth 系统身份验证更新此实用程序方法。 方法如下:

   public static void SendMail(string to, string cc, string bcc, string replyTo, string from, string subject, bool isHtmlFormat, string body, string[] attachments)
    {
        var cca = ConfidentialClientApplicationBuilder.Create("my-app-id")//app id
                                                      .WithClientSecret("my-client-secret") //Client secret
                                                      .WithTenantId("my-tenant-id") //Id tenant
                                                      .Build();

        var authResult = cca.AcquireTokenForClient(new string[] { "https://outlook.office365.com/.default" }).ExecuteAsync().Result;

        string[] recipients = to.Replace(" ", "").Split(';');
        string[] repliesTo  = string.IsNullOrWhiteSpace(replyTo) ? Array.Empty<string>() : replyTo.Replace(" ", "").Split(';');
        string[] ccs        = string.IsNullOrWhiteSpace(cc)      ? Array.Empty<string>() : cc.Replace(" ", "").Split(';');
        string[] bccs       = string.IsNullOrWhiteSpace(bcc)     ? Array.Empty<string>() : bcc.Replace(" ", "").Split(';');

        ExchangeService service = new ExchangeService
        {
            Url                = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
            Credentials        = new OAuthCredentials(authResult.AccessToken),
            ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, from)
        };

        service.HttpHeaders.Add("X-AnchorMailbox", from); //Include x-anchormailbox header

        EmailMessage emailMessage = new EmailMessage(service)
        {
            From = new EmailAddress(from),
            Subject = subject, 
            Body = new MessageBody(isHtmlFormat ? BodyType.HTML : BodyType.Text, body)
            
        };

        emailMessage.ToRecipients.AddRange(recipients);
        emailMessage.ReplyTo.AddRange(repliesTo);
        emailMessage.CcRecipients.AddRange(ccs);
        emailMessage.BccRecipients.AddRange(bccs);

        foreach (string attachment in attachments ?? Array.Empty<string>())
        {
            emailMessage.Attachments.AddFileAttachment(attachment);
        }

        emailMessage.Send();
    }

该函数的调用方式非常简单:

MailHelper.SendMail("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8cc1f5c9e1ede5e0cce1f5cfe3e1fcede2f5a2efe3e1" rel="noreferrer noopener nofollow">[email protected]</a>", null, null, null, "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fab495a89f8a9683ba9783b995978a9b9483d4999597" rel="noreferrer noopener nofollow">[email protected]</a>", "Test subject", false, "This is a test body", null);

问题在于,只要 Method emailMessage.Send();调用时,会抛出 Microsoft.Exchange.WebServices.Data.ServiceRequestException 报告 403 禁止错误。

我已经在 Azure Active Directory 界面中注册了该应用程序,设置了密码并设置了以下权限: enter image description here

我的租户中的帐户设置为允许 Exchange 服务: permissions

我已经仔细检查了 ID 和帐户名称,以确保这不是一个小错误,但我不是 EWS 方面的专家,所以我肯定遗漏了一些东西,不幸的是我不知道在哪里。

感谢您的提前。

最佳答案

如果您没有所需的权限或错过了对添加的 API 权限授予管理员同意,通常会出现 403 Forbidden 错误。

注意,您提到的代码使用的是“客户端凭据流”,仅适用于应用程序权限,但您添加了所有<强>委派权限。

在这种情况下,即使您同意委派权限,您也会收到 403 Forbidden 错误。

我尝试通过 Postman 在我的环境中重现相同的结果,并得到以下结果:

我创建了一个 Azure AD 应用程序并添加了 API 权限,如下所示:

enter image description here

现在,我通过Postman使用“客户端凭据流”生成了访问 token ,如下所示:

POST https://login.microsoftonline.com/tenantID/oauth2/v2.0/token
client_id:appID
grant_type:client_credentials
client_secret:secret
scope:https://graph.microsoft.com/.default

回应:

enter image description here

当我使用上述 token 通过以下查询发送邮件时,我收到如下 403 Forbidden 错误:

POST https://graph.microsoft.com/v1.0/users/userID/sendmail

回应:

enter image description here

解决错误,您需要添加应用程序权限并授予管理员同意 给他们如下:

enter image description here

现在我再次生成访问 token ,并在运行下面的查询中使用它来发送示例邮件:

enter image description here

根据您的情况,通过授予管理员同意来添加应用程序权限,然后再次运行代码。

关于c# - 发送邮件时出现 EWS 和 OAuth 403 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74125340/

相关文章:

c# - 如何在我的项目中包含可执行文件并在 .NET 中调用它

javascript - 找不到可变的azure移动应用程序

azure - 将用户/组和角色添加到 Azure AD native 应用程序

c# - WebAPI 使用用户名和密码对 Azure AD 进行非交互式身份验证

ios - 如何在 iOS 中使用 Objective-C 进行 POST 调用和发送参数

c# - 可选参数odata函数c#

c# - Mvc ViewBag - 无法将 null 转换为 'bool',因为它是不可为 null 的值类型

c# - 用于声明显式类型而不是 var 的 Linq 语法

javascript - 实现 Oauth。第三方认证后应该重定向到哪里?

git - 将文件提交到 github,然后取消暂存,因为它包含敏感数据