Overview
Tracking mailbox sizes in Office 365 is critical for managing storage and preventing disruptions.
Our tenant has a large number of mailboxes. We needed a way to check active users and their current storage usage accurately.
Microsoft’s built-in tools lag by multiple days and don’t provide a real-time view of mailbox sizes.
To solve this, I created a PowerShell script that:
- Pulls real-time mailbox size data using Microsoft’s CLI tools
- Targets a specific distribution list instead of scanning the entire tenant
- Exports results to a CSV file for tracking and analysis
- Ensures we work with up-to-date and accurate data
This approach helps IT teams proactively manage storage and avoid mailbox overages.
What This Script Does
Retrieves:
- User’s name & email address
- Mailbox size in GB
- Whether archive is enabled
- Retention policy assigned
- Number of mailbox items
- Archive size
- Auto-Archive status
Targets:
- A specific distribution list instead of scanning all mailboxes.
Outputs:
- A CSV file that can be opened in Excel for easy analysis.
Requirements
Before running this script, ensure you have:
- PowerShell 5.1+
- Exchange Online PowerShell Module
- Administrator privileges
- A distribution list containing all users you need to check
The PowerShell Script
# Define the group email address
$groupEmail = "staff@domain.com"
# Get members of the distribution group
$groupMembers = Get-DistributionGroupMember -Identity $groupEmail |
Select-Object Name, DisplayName, PrimarySmtpAddress, RecipientType
# Export to CSV
$exportPath = "C:\365_reports\staff_" + (Get-Date -Format "yyyyMMdd") + ".csv"
$groupMembers | Export-Csv -Path $exportPath -NoTypeInformation
Write-Output "Group members exported to $exportPath"
# Target only Members of Staff + AutoExpand
$staffGroupMembers = Get-DistributionGroupMember -Identity "staff@domain.com" | Where-Object { $_.RecipientType -eq 'UserMailbox' }
# Fetch mailbox statistics for group members only
$staffGroupMembers |
ForEach-Object {
$mailboxDetails = Get-Mailbox -Identity $_.PrimarySmtpAddress
$stats = Get-MailboxStatistics -Identity $_.PrimarySmtpAddress
$archiveStats = Get-MailboxStatistics -Archive -Identity $_.PrimarySmtpAddress
$totalItemSizeGB = switch ($stats.TotalItemSize.ToString().Split(" ")[1]) {
"KB" { [math]::Round([double]$stats.TotalItemSize.ToString().Split(" ")[0] / 1MB, 2) }
"MB" { [math]::Round([double]$stats.TotalItemSize.ToString().Split(" ")[0] / 1KB, 2) }
"GB" { [math]::Round([double]$stats.TotalItemSize.ToString().Split(" ")[0], 2) }
Default { [double]$stats.TotalItemSize.ToString().Split(" ")[0] }
}
$archiveStatus = if ($archiveStats.ArchiveQuota -ne "0 B") {"Enabled"} else {"Disabled"}
$autoArchiveEnabled = if ($mailboxDetails.AutoExpandingArchiveEnabled) {"Enabled"} else {"Disabled"}
$_ | Select-Object DisplayName,
PrimarySmtpAddress,
@{Name="RetentionPolicy";Expression={$mailboxDetails.RetentionPolicy}},
@{Name="TotalItemSizeGB";Expression={$totalItemSizeGB}},
@{Name="ItemCount";Expression={$stats.ItemCount}},
@{Name="ArchiveStatus";Expression={$archiveStatus}},
@{Name="ArchiveSize";Expression={$archiveStats.TotalItemSize}},
@{Name="AutoArchiveEnabled";Expression={$autoArchiveEnabled}}
} |
Export-Csv -Path ("C:\365_reports\StaffMailboxStatistics_" + (Get-Date -Format "yyyyMMdd") + ".csv") -NoTypeInformation
Script Breakdown & Customization Guide
1. Define the Distribution List
$groupEmail = "staff@domain.com"
Replace staff@domain.com with your distribution list. Ensure the list includes only active users.
2. Get Distribution List Members
$groupMembers = Get-DistributionGroupMember -Identity $groupEmail |
Select-Object Name, DisplayName, PrimarySmtpAddress, RecipientType
Retrieves users from the distribution list and selects name, display name, email, and recipient type.
3. Export Members to CSV
$exportPath = "C:\365_reports\staff_" + (Get-Date -Format "yyyyMMdd") + ".csv"
$groupMembers | Export-Csv -Path $exportPath -NoTypeInformation
Saves the list to a CSV file using the current date in the filename. Change the file path if needed.
4. Target Only User Mailboxes
$staffGroupMembers = Get-DistributionGroupMember -Identity "staff@domain.com" | Where-Object { $_.RecipientType -eq 'UserMailbox' }
Filters for user mailboxes only — excludes shared mailboxes and groups.
5. Get Mailbox Statistics
$staffGroupMembers |
ForEach-Object {
$mailboxDetails = Get-Mailbox -Identity $_.PrimarySmtpAddress
$stats = Get-MailboxStatistics -Identity $_.PrimarySmtpAddress
$archiveStats = Get-MailboxStatistics -Archive -Identity $_.PrimarySmtpAddress
Retrieves mailbox size, item count, archive status, and retention policy.
6. Convert Mailbox Size to GB
$totalItemSizeGB = switch ($stats.TotalItemSize.ToString().Split(" ")[1]) {
"KB" { [math]::Round([double]$stats.TotalItemSize.ToString().Split(" ")[0] / 1MB, 2) }
"MB" { [math]::Round([double]$stats.TotalItemSize.ToString().Split(" ")[0] / 1KB, 2) }
"GB" { [math]::Round([double]$stats.TotalItemSize.ToString().Split(" ")[0], 2) }
Default { [double]$stats.TotalItemSize.ToString().Split(" ")[0] }
}
Converts mailbox size to GB for consistent reporting.
7. Check Archive & Retention Policies
$archiveStatus = if ($archiveStats.ArchiveQuota -ne "0 B") {"Enabled"} else {"Disabled"}
$autoArchiveEnabled = if ($mailboxDetails.AutoExpandingArchiveEnabled) {"Enabled"} else {"Disabled"}
Checks if archive is enabled and determines auto-archiving status.
8. Export the Final Report
$_ | Select-Object DisplayName,
PrimarySmtpAddress,
@{Name="RetentionPolicy";Expression={$mailboxDetails.RetentionPolicy}},
@{Name="TotalItemSizeGB";Expression={$totalItemSizeGB}},
@{Name="ItemCount";Expression={$stats.ItemCount}},
@{Name="ArchiveStatus";Expression={$archiveStatus}},
@{Name="ArchiveSize";Expression={$archiveStats.TotalItemSize}},
@{Name="AutoArchiveEnabled";Expression={$autoArchiveEnabled}}
Selects all fields for the report. Modify as needed to include or exclude fields.
9. Save the Report with a Timestamp
Export-Csv -Path ("C:\365_reports\StaffMailboxStatistics_" + (Get-Date -Format "yyyyMMdd") + ".csv") -NoTypeInformation
Saves the final report as a CSV with a date-stamped filename.
Summary of Changes to Make
| Section | Change |
|---|---|
| Define Distribution List | Update to your group email |
| File Export Path | Change where reports are saved |
| Fields in Report | Add or remove fields |
| Data Filtering | Adjust mailbox type filters |
Final Thoughts
This script helps Exchange admins automate mailbox monitoring. Customize the distribution list, fields, and export path to fit your needs.
Need help customizing the script? Email me!