Exchange Web Services (EWS) was launched with support for Basic Authentication. Over the last few years, Microsoft pushing us to stop using basic authentication and recommend using Modern Authentication (OAuth 2.0). Here will explore how to get EWS Access Token with Modern authentication and use the token to connect EWS API.
We have used the EWS API 2.2 DLL in the below script, install the EWS Managed API 2.2 and ensure the DLL file (Microsoft.Exchange.WebServices.dll) is available in the correct location. You can download the EWS API 2.2 setup from this GitHub link.
Summary
- Connect EWS API using Basic Authentication
- Connect EWS API using Modern Authentication
- Get EWS Access Token and Connect Mailbox using the OAuth Token
Connect EWS API using Basic Authentication
The following script uses the basic authentication to connect the Exchange Online mailbox using Exchange Web Services (EWS).
#Import EWS API dll
Import-Module "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
#Provide the mailbox id (email address) to connect
$MailboxName ="[email protected]"
#Provide the mailbox user credentials
$PSCredential = Get-Credential
$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()
#Use Basic Authentication
$Service.Credentials = New-Object System.Net.NetworkCredential($PSCredential.UserName.ToString(),$PSCredential.GetNetworkCredential().password.ToString())
#Check EWS connection
$Service.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$Service.AutodiscoverUrl($MailboxName,{$true})
# EWS connection is Success if no error returned.
Connect EWS API using Modern Authentication
To access a mailbox with EWS API using modern authentication, we should have already registered an Azure AD app and configured the Delegated permission | EWS.AccessAsUser.All, and then we should acquire an OAuth Access Token with this application.
Once you have acquired the required access token, set the token to the Credentials property of the $Service object to consume the EWS API with modern authentication.
Import-Module 'C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll'
#Provide the mailbox id (email address) to connect
$MailboxName ="[email protected]"
#Get Access Token with the scope "https://outlook.office.com/EWS.AccessAsUser.All"
$EWSAccessToken="eyJ0eXAi...." #Refer to the below section: "Get EWS Access Token..."
$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()
#Use Modern Authentication
$Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$EWSAccessToken
#Check EWS connection
$Service.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$Service.AutodiscoverUrl($MailboxName,{$true})
#EWS connection is Success if no error returned.
Get EWS Access Token and Connect Mailbox using the OAuth Token
The following commands get Access Token for the Delegated permissions. You should have already created an Azure AD app and configured the Delegated permission “EWS.AccessAsUser.All“. You can refer to this post for more details: How to Register and Configure Azure AD application.
We can use the MSAL.PS library to acquire tokens from the Microsoft identity platform. Run the following command in PowerShell to install this module.
Install-Module -Name MSAL.PS
Run the following commands to get EWS Access Token with your Azure AD app.
#Provide your Office 365 Tenant Id or Tenant Domain Name
$TenantId = "contoso.onmicrosoft.com"
#Used the Microsoft Graph PowerShell app id. You can create and use your own Azure AD App id if needed.
$AppClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e"
$MsalParams = @{
ClientId = $AppClientId
TenantId = $TenantId
Scopes = "https://outlook.office.com/EWS.AccessAsUser.All"
}
$MsalResponse = Get-MsalToken @MsalParams
$EWSAccessToken = $MsalResponse.AccessToken
Now you have successfully acquired the EWS OAuth Access token with Modern authentication. You can use this token to access your Exchange Online mailbox using the Exchange Web Services (EWS API).
Import-Module 'C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll'
#Provide the mailbox id (email address) to connect
$MailboxName ="[email protected]"
$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()
#Use Modern Authentication
$Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$EWSAccessToken
#Check EWS connection
$Service.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$Service.AutodiscoverUrl($MailboxName,{$true})
#EWS connection is Success if no error returned.
Hi,
Thanks for usefull post! Unfortunatly i’m bouncing against an error when I try the following command:
$Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$EWSAccessToken
The error states says: “Unable to find type [Microsoft.Exchange.WebServices.Data.OAuthCredentials].”
Does this has to do something with the dll I imported? I’m using the EWS 2.2.
Kind regards,
Yes, you should have installed the EWS Managed API 2.2 and ensured the DLL file (Microsoft.Exchange.WebServices.dll) is available in the correct location. If needed, you can download the EWS Managed API 2.2 setup from this GitHub link: https://github.com/morgantechspace/PowerShell/blob/main/EWSManagedAPI2.2.msi
Hi
I’m getting
Exception calling “FindFolders” with “2” argument(s): “ExchangeImpersonation SOAP header must be present for this type of OAuth token.”
On $FoldersResult = $Service.FindFolders([Microsoft.Exchange.Webservices.Data.WellKnownFolderName]::Inbox, $Folderview)
Hi,
I’m receiving the following error for the AutoDiscoverUrl:
$Service.AutodiscoverUrl($MailboxName,{$true})
Exception calling “AutodiscoverUrl” with “2” argument(s): “The Autodiscover service couldn’t be located.”
At line:1 char:1
+ $Service.AutodiscoverUrl($MailboxName,{$true})
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : AutodiscoverLocalException
I have EWS 2.2 installed and pointed to the Microsoft.Exchange.WebServices.dll. Am I missing something else?
Thanks
1. Ensure that you have provided the correct email address.
2. Ensure that you have provided the correct user credentials
3. If you tried modern authentication, then just check with the basic authentication and vice-versa to ensure the credentials are correct.
Hi. I am trying to use a Secret ID with the $MsalParams object and I get a token (which doesn’t look any different each time I run the get token portion of the code), and when I do the AudoDiscoverUrl() I get this error:
Exception calling “AutodiscoverUrl” with “2” argument(s): “The expected XML node type was XmlDeclaration, but the actual type is Element.”
If I remove the Secret ID parameter, it works, but I have to manually enter username and password each time the login prompt appears (after 60 mins of default expiration).
I am trying to automate all this so I can pull email attachments from an AD mailbox.
Thanks
If I use this code do I need to change the Scope parameter value because I use EWS instead Graph API? Just to make sure I will get EWS Token.
#Provide your Office 365 Tenant Domain Name or Tenant Id
$TenantId = “contoso.onmicrosoft.com”
#$TenantId = “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”
#Provide Application (client) Id of your app
$AppClientId=”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”
#Provide Application client secret key
$ClientSecret =”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
$RequestBody = @{client_id=$AppClientId;client_secret=$ClientSecret;grant_type=”client_credentials”;scope=”https://graph.microsoft.com/.default”;}
$OAuthResponse = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token -Body $RequestBody
$AccessToken = $OAuthResponse.access_token
Then after I will this code you provide:
Import-Module ‘C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll’
#Provide the mailbox id (email address) to connect
$MailboxName =”[email protected]”
$Service = [Microsoft.Exchange.WebServices.Data.ExchangeService]::new()
#Use Modern Authentication
$Service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$AccessToken
#Check EWS connection
$Service.Url = “https://outlook.office365.com/EWS/Exchange.asmx”
$Service.AutodiscoverUrl($MailboxName,{$true})
#EWS connection is Success if no error returned.