Entra / Microsoft 365 · Exchange Online
Check shared mailbox quotas
Example of how to check the current quota usage of shared mailboxes and email.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnline
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([string] $TenantId = "a662313f-14fc-43a2-9a7a-d2e27f4f3478" # Define your tenant identifier here",[string] $AppId = "d86b1929-b818-411b-834a-206385bf5347" # Define the app identifier",[string] $CertThumbPrint = "F79286DB88C21491110109A0222348FACF694CBD" # Define the certificate thumbprint")Function Add-MessageRecipients {# Function to build an addressee list to send email[cmdletbinding()]Param([array]$ListOfAddresses )ForEach ($SMTPAddress in $ListOfAddresses) {@{emailAddress = @{address = $SMTPAddress}}}}# Need to connect to Exchange Online to get mailbox informationIf ($Null -eq (Get-ConnectionInformation)) {Connect-ExchangeOnline}# Connect to the Graph to retrieve information about mailbox licenses and send messages. This# uses an Entra ID registered app authenticated using a client thumbprint. The app has consent for the# necessary User.Read.All and Mail.Send.All permissions.# Get rid of any existing Graph sessions to make sure that we pick up the correct permissionsDisconnect-MgGraph | Out-NullConnect-MgGraph -NoWelcome -TenantId $TenantId -AppId $AppId -CertificateThumbprint $CertThumbPrint# Mailbox to receive notifications when a shared mailbox has no registered user with full access$DefaultNotificationAddress = "Lotte.Vetler@Office365itpros.com"# Address to send notification messages from$MailSentFrom = "Azure.Management.Account@office365itpros.com"# Service plan identifiers to check for licensing[array]$ServicePlans = "efb87545-963c-4e0d-99df-69c6916d9eb0"Write-Host "Searching for shared mailboxes..."[array]$SharedMailboxes = Get-ExoMailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited -PropertySet Quota -Properties DisplayNameIf (!($SharedMailboxes)) {Write-Host "Can't find any shared mailboxes to process"} Else {$QuotaReport = [System.Collections.Generic.List[Object]]::new()ForEach ($Mbx in $SharedMailboxes) {$ExoP2 = $False; $NoOwnerFlag = $FalseWrite-Host "Checking accounts with full access rights to shared mailbox..."[array]$Owners = Get-ExoMailboxPermission -Identity $Mbx.ExternalDirectoryObjectId | Where-Object {$_.User -ne "NT AUTHORITY\SELF"} | `Select-Object User, AccessRights | Where-Object {$_.AccessRights -Like "FullAccess"} | Select-Object -ExpandProperty UserIf (!($Owners)) { # No owners found - use default notification address$Owners += $DefaultNotificationAddress$NoOwnerFlag = $TrueWrite-Host ("No owners found for mailbox {0}" -f $Mbx.DisplayName) -ForegroundColor Red} Else {[array]$ExpandedOwners = $NullForEach ($Owner in $Owners) {$OwnerType = (Get-EXORecipient -Identity $Owner).RecipientTypeDetailsSwitch ($OwnerType) {"MailUniversalSecurityGroup" {$ExpandedOwners += (Get-DistributionGroupMember -Identity $Owner).PrimarySmtpAddress }"UserMailbox" {$ExpandedOwners += $Owner }}}[array]$Owners = $ExpandedOwners | Sort-Object -Unique$OutputOwners = $Owners -join ", "Write-Host ("Found owners {0} for mailbox {1}" -f $OutputOwners, $Mbx.DisplayName )}# Check if the shared mailbox has an Exchange Online Plan 2 license to allow for a larger quota[array]$Licenses = Get-MgUserLicenseDetail -UserId $Mbx.ExternalDirectoryObjectIdIf ($Licenses) {[array]$ServicePlansMbx = $Licenses.ServicePlans | Where-Object {$_.ProvisioningStatus -eq "Success"} | Select-Object -ExpandProperty ServicePlanIdForEach ($SP in $ServicePlans) {If ($SP -in $ServicePlansMbx) {Write-Host ("Exchange Online Service Plan 2 found for mailbox {0}" -f $Mbx.displayName )$ExOP2 = $True}}}Write-Host "Fetching mailbox usage statistics"[array]$MbxStats = Get-ExoMailboxStatistics -Identity $Mbx.ExternalDirectoryObjectId[INT64]$QuotaUsed = [convert]::ToInt64(((($MbxStats.TotalItemSize.ToString().split("(")[-1]).split(")")[0]).split(" ")[0]-replace '[,]',''))# Byte count for mailbox quota[INT64]$MbxQuota = [convert]::ToInt64(((($Mbx.ProhibitSendReceiveQuota.ToString().split("(")[-1]).split(")")[0]).split(" ")[0]-replace '[,]',''))$MbxQuotaGB = [math]::Round(($MbxQuota/1GB),2)$QuotaPercentUsed = [math]::Round(($QuotaUsed/$MbxQuota)*100,2)$QuotaUsedGB = [math]::Round(($QuotaUsed/1GB),2)$ReportLine = [PSCustomObject]@{Mailbox = $Mbx.IdentityName = $Mbx.DisplayNameEmail = $Mbx.PrimarySmtpAddressQuota = ("{0} GB" -f $MbxQuotaGB)Items = $MbxStats.ItemCountSize = ("{0} GB" -f $QuotaUsedGB)"% Used" = $QuotaPercentUsedOwners = $OwnersLicense = $EXOP2"No Owner" = $NoOwnerFlag}$QuotaReport.Add($ReportLine)}}# Code to email the owners of each shared mailbox[int]$i=0ForEach ($Item in $QuotaReport) {Write-Host ("Sending notification message for mailbox {0}" -f $Item.Name)# Get the list of shared mailbox owners$EmailRecipients = @( $Item.Owners.Split(",").Trim() )# Add them as message recipients[array]$MsgToRecipients = Add-MessageRecipients -ListOfAddresses $EmailRecipients$MsgSubject = ("Shared Mailbox Quota Information for {0}" -f $Item.Mailbox)$HtmlHead = "<h2>Mailbox Quota Information</h2><p>The current quota information for the shared mailbox is as follows.</p>"$HtmlBody = $Item | ConvertTo-Html -Fragment$HtmlMsg = "</body></html><p>" + $HtmlHead + $Htmlbody + "<p>"# Construct the message body$MsgBody = @{Content = "$($HtmlMsg)"ContentType = 'html'}$Message = @{subject = $MsgSubject}$Message += @{toRecipients = $MsgToRecipients}$Message += @{body = $MsgBody}$Params = @{'message' = $Message}$Params += @{'saveToSentItems' = $True}$Params += @{'isDeliveryReceiptRequested' = $True}# And send the message using the parameters that we've filled inSend-MgUserMail -UserId $MailSentFrom -BodyParameter $Params$i++}Write-Host ("Processing complete and quota usage notifications sent for {0} mailboxes" -f $i)
Parameters
ParameterDefaultNotes
-TenantIda662313f-14fc-43a2-9a7a-d2e27f4f3478" # Define your tenant identifier hereMicrosoft Entra tenant ID for app-only Graph authentication.-AppIdd86b1929-b818-411b-834a-206385bf5347" # Define the app identifierApplication (client) ID for the app registration used to connect.-CertThumbPrintF79286DB88C21491110109A0222348FACF694CBD" # Define the certificate thumbprintCertificate thumbprint for app-only Graph authentication.Attribution
Author
Office365itpros