MastErAldo
MastErAldo

Reputation: 674

Sending mail with EWS and OAuth 403 error

A while ago I wrote in C# a simple utility method that was called by an application to send emails automatically.

The application used to authenticate in EWS with Basic authentication (username + password) and everything worked fine.

Starting from September 2022 Microsoft started disabling this now deprecated authentication method, so I decided to update this utility method with an OAuth system autentication. The method is the following:

   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();
    }

The function is called in a very straightforward way:

MailHelper.SendMail("[email protected]", null, null, null, "[email protected]", "Test subject", false, "This is a test body", null);

The problem is that as soon as the Method emailMessage.Send(); is called, a Microsoft.Exchange.WebServices.Data.ServiceRequestException reporting a 403 forbidden error is thrown.

I already registered the app in the Azure Active Directory interface, set a secret and set the following permissions: enter image description here

The accounts in my tenant are set to allow Exchange services: permissions

I already double checked IDs and account names to be sure it was not a trivial mistake, but I'm not an expert when it comes to EWS, so I'm surely missing something, unfortunately I don't know where.

Thanks id advance.

Upvotes: 3

Views: 3422

Answers (1)

Sridevi
Sridevi

Reputation: 22637

The error 403 Forbidden usually occurs if you don't have required permissions or missed granting admin consent to the added API permissions.

Please note that, the code you mentioned is using "Client credentials flow" that works with only Application permissions but you added all Delegated permissions.

In that case, you will get 403 Forbidden error even you granted consent to Delegated permissions.

I tried to reproduce the same in my environment via Postman and got the below results:

I created one Azure AD application and added API permissions same as you like below:

enter image description here

Now, I generated an access token using "Client credentials flow" via Postman like below:

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

Response:

enter image description here

When I used the above token to send mail with below query, I got 403 Forbidden error like this:

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

Response:

enter image description here

To resolve the error, you need to add Application permissions and grant admin consent to them like below:

enter image description here

Now I generated the access token again and used it in running below query to send sample mail:

enter image description here

In your case, add Application permissions by granting admin consent to them and run the code again.

Upvotes: 3

Related Questions