Entra / Microsoft 365 · Users & guests
Report user inbox count
A script to show how to fetch mailbox folder statistics using a combination of PowerShell and the Microsoft Graph ListFolders API.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Import-Module ImportExcel -ErrorAction SilentlyContinue
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([string] $TenantId = "",[string] $AppId = "")Clear-Host# Check that we are connected to Exchange OnlineImport-Module ImportExcel -ErrorAction SilentlyContinue$ExcelAvailable = $True[array]$ModulesLoaded = Get-Module | Select-Object -ExpandProperty NameIf ("ExchangeOnlineManagement" -notin $ModulesLoaded) {Write-Host "Please connect to the Exchange Online Management module and then restart the script"Break}# See if we can use ImportExcelIf ("ImportExcel" -notin $ModulesLoaded) {$ExcelAvailable = $False}$ExcelOutput = "c:\temp\UserInboxCounts.xlsx"$CSVOutput = "c:\temp\UserInboxCounts.csv"# Define the values applicable for the application used to connect to the Graph - change these for your tenant# to use the app id and app secret for the Azure AD registered app you want to use for this script$AppSecret = 'yVh8Q~oA9.QJchbNqSDd89Iz1-xNTZ9m8PPVYdgP'# Construct URI and body needed for authentication$uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"$body = @{client_id = $AppIdscope = "https://graph.microsoft.com/.default"client_secret = $AppSecretgrant_type = "client_credentials"}# Get OAuth 2.0 Token$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing# Unpack Access Token$token = ($tokenRequest.Content | ConvertFrom-Json).access_token$Headers = @{'Content-Type' = "application\json"'Authorization' = "Bearer $Token"'ConsistencyLevel' = "eventual" }Write-Host "Finding user mailboxes..."[array]$Mbx = Get-ExoMailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox | Sort-Object DisplayNameIf (!($Mbx)) { Write-Host "No mailboxes found... exiting!" ; break }$Report = [System.Collections.Generic.List[Object]]::new()$i = 1ForEach ($M in $Mbx) {Write-Host ("Processing mailbox {0} of {1}: {2}" -f $i, $Mbx.Count, $M.DisplayName); $i++$Uri = "https://graph.microsoft.com/v1.0/users/" + $M.ExternalDirectoryObjectId + "/mailFolders?`$top=250"$FolderData = Invoke-RestMethod -Headers $Headers -Uri $Uri -UseBasicParsing -Method "GET" -ContentType "application/json"$InboxData = $FolderData.Value | Where-Object {$_.displayname -eq "Inbox"}$TotalMbxItems = ($FolderData.Value.totalitemcount | Measure-Object -Sum | Select-Object -ExpandProperty Sum)$TotalMbxSize = ($FolderData.Value.SizeInBytes | Measure-Object -Sum | Select-Object -ExpandProperty Sum)$ReportLine = [PSCustomObject][Ordered]@{ # Write out details of the mailbox"User" = $M.DisplayNameUPN = $M.UserPrincipalNameInboxCount = $InboxData.totalItemCountUnreadCount = $InboxData.unreadItemCountTotalMbxFolders = $FolderData.Value.CountTotalMbxItems = $TotalMbxItemsTotalMbxFolderSize = [math]::Round($TotalMbxsize/1Mb,2) }$Report.Add($ReportLine)}# If you don't have the ImportExcel module available, you can change this to export to a CSV file using the Export-CSV cmdlet$Report | Sort-Object UnreadCount -DescendingIf ($ExcelAvailable -eq $True) {Export-Excel -Path $ExcelOutput -WorkSheetName "Inbox Counts" -TableStyle Medium16 `-Title "Inbox Data for Mailboxes"Write-Host ("Excel worksheet available in {0}" -f $ExcelOutput)} Else {Export-CSV -NoTypeInformation $CSVOutputWrite-Host ("CSV file available in {0}" -f $CSVOutput)}
Parameters
ParameterDefaultNotes
-TenantId""Microsoft Entra tenant ID for app-only Graph authentication.-AppId""Application (client) ID for the app registration used to connect.Attribution
Author
Office365itpros