Exchange Online: Create Custom Folder in Mailboxes using Graph API and PowerShell
Applies To
This article applies to: Exchange Online, Graph API
1. Introduction
This article is exploring the step-by-step procedure to create Custom Folder for all Exchange Online Mailboxes using Graph API. Using the cmdlet New-MailboxFolder, Administrators can’t create folders in other mailboxes. So, they have to use an alternate option like Graph API, where there is a special requirement to access all the mailboxes in your Exchange Online Organization.
1.1 What is GRAPH API?
The Microsoft Graph API is a RESTful web API that enables you to access Microsoft Cloud service resources. After you register your app and get authentication tokens for a user or service, you can make requests to the Microsoft Graph API. For more information, see Overview of Microsoft Graph.
Microsoft Graph exposes REST APIs and client libraries to access data on the following Microsoft 365 services:
- Office 365 services: Delve, Excel, Microsoft Bookings, Microsoft Teams, OneDrive, OneNote, Outlook/Exchange, Planner, and SharePoint
- Enterprise Mobility and Security services: Advanced Threat Analytics, Advanced Threat Protection, Azure Active Directory, Identity Manager, and Intune
- Windows 10 services: activities, devices, notifications
- Dynamics 365 Business Central
1.2 Prerequisites
Following are the system pre-requisites to be set in your work place to go for the procedure I am explaining herewith
- Windows PowerShell 5.1
- Azure tenant and Exchange Online account Access
- App registration permissions on the Azure subscription
2 Steps to be followed in Azure Portal
2.1 Create an Application Identity in Azure Portal
In this example, I am showing a method in which, you can access the Microsoft Graph API with an OAuth token.
The following steps will help to create an application Identity in your Azure Tenant with privileges to access the Exchange Online Mailboxes
2.1.1 Application Registration
Login Azure Portal and search for ‘Application Registrations’ as below and select 'Register an Application'
http://cloudcompute.info/wp-content/uploads/2020/06/image-7.png
http://cloudcompute.info/wp-content/uploads/2020/07/image.png
2.1.2 Application Name
Name your application and follow the below settings
http://cloudcompute.info/wp-content/uploads/2020/07/image-1.png
2.1.3 Application Details
Application ID Details can be noted from the following window:
2.1.4 Application Secret
Create an Application Secret by clicking 'New Client Secret' from the following page and note down the **value **for further reference in upcoming steps.
2.2 Application Permissions
2.2.2 Assign API Permission
Assign required API permissions so that we can access Exchange Online mailboxes as shown below:
http://cloudcompute.info/wp-content/uploads/2020/07/image-5.png
Select Graph ‘Application permission’ for the purpose of mailbox access as below and save
http://cloudcompute.info/wp-content/uploads/2020/07/image-8.png
2.2.2 Grant Admin Consent
Grand Admin Consent to the selected permissions in the tenant. Finally, your permissions page will show as follows
http://cloudcompute.info/wp-content/uploads/2020/07/image-9.png
3 POWERSHELL Exercise
3.1 Script Variables
Edit the following parameters as needed for your tenant settings
$Mailboxes = @(“mailbox1@domain.com”,”mailbox2@domain.com”)$Folders = @(“folder1″,”folder2”)$AppId = ‘Your App ID’$AppSecret = ‘Your app secret’$TenantName = “yourtenantname.onmicrosoft.com”
3.2 PowerShell Code
Copy the following cmdlet to a notepad and save as .ps1 file. Note that you have to edit the variables as stated above
##Create Custom Folder for Exchange Online Mailboxes using Graph API
$Mailboxes = @("mailbox1@domain.com","mailbox2@domain.com")
$Folders = @("folder1","folder2")
$AppId = 'Your App ID'
$AppSecret = 'Your app secret'
$Scope = "https://graph.microsoft.com/.default"
$TenantName = "yourtenantname.onmicrosoft.com"
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
# Add System.Web for urlencode
Add-Type -AssemblyName System.Web
# Create body
$Body = @{
client_id = $AppId
client_secret = $AppSecret
scope = $Scope
grant_type = 'client_credentials'
}
# Splat the parameters for Invoke-Rest method for cleaner code
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
# Create string by joining bodylist with '&'
Body = $Body
Uri = $Url
}
# Request the token!
$Request = Invoke-RestMethod @PostSplat
# Create header
$Header = @{
Authorization = "$($Request.token_type) $($Request.access_token)"
}
## Access Mailboxes
foreach($mailbox in $Mailboxes) {
$Uri = "https://graph.microsoft.com/v1.0/users/$mailbox/mailFolders"
## Fetch Folder Names
$Mailboxfolders = Invoke-RestMethod -Uri $Uri -Headers $Header -Method Get -ContentType "application/json"
$MailboxfoldersList = $Mailboxfolders.Value.Displayname
$NextPage = $Mailboxfolders.'@Odata.NextLink'
While($NextPage -ne $Null){
$Mailboxfolders = Invoke-RestMethod -Uri $NextPage -Headers $Header -Method Get -ContentType "application/json"
$MailboxfoldersList += $Mailboxfolders.Value.Displayname
$NextPage = $Mailboxfolders.'@Odata.NextLink'
}
## Loop folders
foreach($Folder in $Folders) {
$Body = @"
{
"displayName": "$Folder"
}
"@
## Show Progress
Write-Host "Checking the folder with similar name..."
if($($MailboxfoldersList) -contains $folder) {
write-host "$folder already exists. Unable to create the folder..."
}
else {
$Newfolder = Invoke-RestMethod -Uri $Uri -Headers $Header -Method Post -Body $Body -ContentType "application/json"
write-host "Created Folder: $($Newfolder.displayName) in mailbox $mailbox...`n"
}
}
}
3.3 Sample Script execution and output in PowerShellhttp://cloudcompute.info/wp-content/uploads/2020/07/image-11.png
4. Verification of the result in Mailbox
As you can see from the PowerShell report above, folders are being created and you may verify this from your mailboxes too in Outlook or OWA
5. Conclusion
As I mentioned at the introduction of this article, Exchange Online Tenant admins can't create mailboxes across the tenant using the cmdlet New-MailboxFolder, andGraph API is a better alternate when they have such a requirement.