Exchange Online IMAP and SMTP OAuth 2.0 with Delegated Permissions
Hi All,
This Week i had to Troubleshoot an Application with IMAP and SMTP Access to a Shared Mailbox that uses Microsoft Graph Delegated Permissions.
I’ve already blogged about how to Use Application Permissions
- Exchange Online POP and IMAP OAuth 2.0 Client Credentials Flow
- Exchange Online - Other ways of Testing IMAP OAuth2 Client Credential Flow
Register Azure AD (EntraID) Application
Register a new Application
Note down the following:
- Display name
- Application ID
- Tenant ID
Click on “Add a Redirect URI”
Click on “Mobile and desktop applications”
Enable the (MSAL only) and copy the Redirect URI
On the “API Permissions” remove the default Permission
Approve with “Yes, remove”
Click on “Add a permission”
Select “Microsoft Graph” and “Delegated permission”
Add “IMAP.AccessAsUser.All”
Add “Mail.Send.Shared”
Click on “Grant admin consent for Icewolf” even if Admin consent required says “no”
Add Exchange Service Principal
First we need to get the Application
###############################################################################
# Get AzureAD Application with Microsoft.Graph PowerShell
###############################################################################
Connect-MgGraph -Scopes 'Application.Read.All'
$AppName = "EXO_IMAP_Delegated"
$Filter = "DisplayName eq '" + $AppName + "'"
$ServicePrincipalDetails = Get-MgServicePrincipal -Filter "$Filter"
$ServicePrincipalDetails
Note: all the code from this Article is also published at my GitHub Repo
Now we can create the Exchange Service Principal
###############################################################################
# Create Exchange Service Principal
###############################################################################
Connect-ExchangeOnline -ShowBanner:$false
New-ServicePrincipal -AppId $ServicePrincipalDetails.AppId -ServiceId $ServicePrincipalDetails.Id -DisplayName "EXO Serviceprincipal $($ServicePrincipalDetails.Displayname)"
Note: The Exchange Service Principal needs to be removed manually when you delete the Azure AD (EntraID) Application Registration.
Now we need to check if IMAP is enabled on the Shared Mailbox
###############################################################################
# CAS Mailbox
###############################################################################
$Mailbox = "SharedMBX@icewolf.ch"
Get-CASMailbox -Identity $Mailbox
Set-CASMailbox -Identity $Mailbox -PopEnabled $false -ImapEnabled $true -SmtpClientAuthenticationDisabled $false
Get-CASMailbox -Identity $Mailbox
Now we need to grant the User the Full Access Permission to the SharedMailbox for the User
###############################################################################
#Full Access
###############################################################################
$Mailbox = "SharedMBX@icewolf.ch"
$User = "a.bohren@icewolf.ch"
#Add FullAccess Permission
Add-MailboxPermission -Identity $Mailbox -User $User -AccessRights FullAccess -AutoMapping $false
#Get FullAccess Permissions
Get-MailboxPermission -Identity $Mailbox | where { ($_.AccessRights -eq "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -like "NT AUTHORITY\SELF") } | ft -AutoSize
Now we need to grant the SendAs Permission to the to the SharedMailbox for the User
###############################################################################
# Send As
###############################################################################
$Mailbox = "SharedMBX@icewolf.ch"
$Trustee = "a.bohren@icewolf.ch"
#Add SendAs Permissions
Add-RecipientPermission -Identity $Mailbox -Trustee $Trustee -AccessRights SendAs
#Get SendAs Permissions
Get-RecipientPermission -Identity $Mailbox | where { ($_.AccessRights -eq "SendAs") -and ($_.IsInherited -eq $false) -and -not ($_.Trustee -like "NT AUTHORITY\SELF") } | ft -AutoSize
Testing
Let’s test if we can get an Access Token
###############################################################################
# Test Token with MSAL and JWTDetails
# Install-Module MSAL.PS
# Install-Module JWTDetails
###############################################################################
$AppID = "e9d3d08b-d477-4688-b972-8cb06eefe439"
$TenantID = "icewolfch.onmicrosoft.com"
$RedirectURI = "msale9d3d08b-d477-4688-b972-8cb06eefe439://auth"
Clear-MsalTokenCache
$Scopes = "https://outlook.office.com/.default"
$Token = Get-MsalToken -Interactive -Scopes $Scopes -TenantID $TenantID -ClientId $AppID -RedirectURI $RedirectURI
$AccessToken = $Token.AccessToken
Get-JWTDetails -token $AccessToken
Now let’s test with the Get-IMAPAccessToken.ps1
###############################################################################
# Test Access
# OAuth2 IMAP Test Tool
# https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1
###############################################################################
Clear-MsalTokenCache
$AppID = "e9d3d08b-d477-4688-b972-8cb06eefe439" #EXO_IMAP_Delegated
$TenantID = "46bbad84-29f0-4e03-8d34-f6841a5071ad"
$RedirectURI = "msale9d3d08b-d477-4688-b972-8cb06eefe439://auth"
.\Get-IMAPAccessToken.ps1 -tenantID $TenantID -clientId $AppID -redirectUri $RedirectURI -LoginHint "a.bohren@icewolf.ch" -SharedMailbox "sharedmbx@icewolf.ch"
Test the Send Mail Functionality
###############################################################################
# Sends Mail via Microsoft Graph API
# https://docs.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=http
###############################################################################
#Delegated (work or school account) Mail.Send
#Delegated (personal Microsoft account) Mail.Send
#Create HTML Body
[string]$body = @"
<html>
<head>
<style>
p {
text-align: Left;
color: green;
font-size: 12px;
font-family: Arial
}
table, th, td {
border: 1px solid;
font-size: 12px;
font-family: Arial
}
</style>
</head>
<body>
<h3>HTML Header</h3>
<p>the quick brown fox jumps over the lazy dog</p>
</body>
</html>
"@
$Mailbox = "sharedmbx@icewolf.ch"
$URI = "https://graph.microsoft.com/v1.0/users/$Mailbox/sendMail"
$ContentType = "application/json"
$Headers = @{"Authorization" = "Bearer "+ $AccessToken}
$Body = @"
{
"message": {
"subject": "Microsoft Graph API Mail DEMO",
"body": {
"contentType": "HTML",
"content": "$Body"
},
"toRecipients": [
{
"emailAddress": {
"address": "a.bohren@icewolf.ch"
}
}
]
}
}
"@
#Send Actual Mail
$result = Invoke-RestMethod -Method "POST" -Uri $uri -Body $Body -Headers $Headers -ContentType $ContentType
If ($null -ne $result)
{
Write-Host "Mail has been sucessufully sent"
}
The Testmail was sucessfully sent with the Shared Mailbox
Test with Remote Connectivity Analizer
You can use also Remote Connectivity Analizer to test the Access.
Select “Office 365” > “Imap Email”
Sign in with OAuth
Sign in with the User
Add the Emailaddress of the Shared Mailbox into the “Alternate Mailbox” field
That worked fine too
Hope this helps you to configure and Test your IMAP,POP3 and SendMail Functionality with delegated Microsoft Graph Permissions.
Regards
Andres Bohren