I have a development environment as below
I have written code below that generates a Token, but when it reaches the line
var folders = _service.FindFolders(WellKnownFolderName.Inbox, new FolderView(10));
It throws error like Microsoft.Exchange.WebServices.Data.ServiceRequestException: 'The request failed. The remote server returned an error: (403) Forbidden.'
Below is the full code
private static void ReadMailsFromExchangeServer()
{
// _service.Credentials = new WebCredentials("test@test.com", "qwerty", "tng");
try
{
string token = GetAccessToken();
ExchangeService _service = new ExchangeService(ExchangeVersion.Exchange2016)
{
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
Credentials = new OAuthCredentials(token),
}; // Use your EWS endpoint
// Impersonate the user you want to act on behalf of
_service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test@test.com");
// Set X-AnchorMailbox header to the SMTP address of the mailbox being accessed
_service.HttpHeaders.Add("X-AnchorMailbox", "test@test.com");//test@test.com
_service.HttpHeaders.Add("X-PreferServerAffinity", "true");
var folders = _service.FindFolders(WellKnownFolderName.Inbox, new FolderView(10));
foreach (var folder in folders)
{
Console.WriteLine(folder.DisplayName);
}
}
catch (Exception ex)
{
}
}
private static async void GetTokens()
{
// Using Microsoft.Identity.Client 4.22.0
var cca = ConfidentialClientApplicationBuilder
.Create(ConfigurationManager.AppSettings["appId"])
.WithClientSecret(ConfigurationManager.AppSettings["clientSecret"])
.WithTenantId(ConfigurationManager.AppSettings["tenantId"])
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
try
{
var authResult = await cca.AcquireTokenForClient(ewsScopes)
.ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
ewsClient.ImpersonatedUserId =
new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test@test.com");
//Include x-anchormailbox header
ewsClient.HttpHeaders.Add("X-AnchorMailbox", "test@test.com");
}
catch (Exception ex)
{
}
}
Initially I got the same error when granted same permissions as you:
The error "The request failed. The remote server returned an error: (403) Forbidden" usually occurs of the application do not have required permissions to perform the action.
Hence to resolve the error, you need to grant Office 365 Exchange Online full_access_as_app
application type API permission to the Microsoft Entra ID application like below:
After granting the required API permission, I am able to fetch the folders successfully:
namespace EWSIntegration
{
class Program
{
static async System.Threading.Tasks.Task Main(string[] args)
{
await ReadMailsFromExchangeServer();
}
private static async System.Threading.Tasks.Task ReadMailsFromExchangeServer()
{
try
{
string token = await GetAccessToken();
ExchangeService _service = new ExchangeService(ExchangeVersion.Exchange2016)
{
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
Credentials = new OAuthCredentials(token),
};
// Impersonate the user you want to act on behalf of
_service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test @test.com");
// Set X-AnchorMailbox header to the SMTP address of the mailbox being accessed
_service.HttpHeaders.Add("X-AnchorMailbox", "test @test.com");
_service.HttpHeaders.Add("X-PreferServerAffinity", "true");
var folders = _service.FindFolders(WellKnownFolderName.Inbox, new FolderView(10));
foreach (var folder in folders)
{
Console.WriteLine($"Folder: {folder.DisplayName}");
}
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
private static async Task<string> GetAccessToken()
{
string clientId = "ClientID";
string clientSecret = "ClientSecret";
string tenantId = "TenantID";
try
{
var cca = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithTenantId(tenantId)
.Build();
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();
return authResult.AccessToken;
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred while acquiring the token: {ex.Message}");
throw;
}
}
}
}