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#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| # 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 ---------------------------------------------------------------------------
# Get members of the distribution group
$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#
This script retrieves mailbox statistics for a specific distribution list in Exchange Online. Follow these steps to customize it for your organization.
1. Define the Distribution List#
1
| $groupEmail = "staff@domain.com"
|
- Replace
staff@domain.com
with your distribution list. - Ensure the list includes only active users.
2. Get Distribution List Members#
1
2
| $groupMembers = Get-DistributionGroupMember -Identity $groupEmail |
Select-Object Name, DisplayName, PrimarySmtpAddress, RecipientType
|
- Retrieves users from the distribution list.
- Selects name, display name, email, and recipient type.
3. Export Members to CSV#
1
2
| $exportPath = "C:\365_reports\staff_" + (Get-Date -Format "yyyyMMdd") + ".csv"
$groupMembers | Export-Csv -Path $exportPath -NoTypeInformation
|
- Saves the list to a CSV file.
- Uses the current date in the filename.
- Change the file path if needed.
4. Target Only User Mailboxes#
1
| $staffGroupMembers = Get-DistributionGroupMember -Identity "staff@domain.com" | Where-Object { $_.RecipientType -eq 'UserMailbox' }
|
- Filters for user mailboxes.
- Excludes shared mailboxes and groups.
5. Get Mailbox Statistics#
1
2
3
4
5
| $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.
- Modify this section to include additional data if needed.
6. Convert Mailbox Size to GB#
1
2
3
4
5
6
| $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.
- Ensures consistent reporting.
7. Check Archive & Retention Policies#
1
2
| $archiveStatus = if ($archiveStats.ArchiveQuota -ne "0 B") {"Enabled"} else {"Disabled"}
$autoArchiveEnabled = if ($mailboxDetails.AutoExpandingArchiveEnabled) {"Enabled"} else {"Disabled"}
|
- Checks if archive is enabled.
- Determines auto-archiving status.
8. Export the Final Report#
1
2
3
4
5
6
7
8
| $_ | 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 fields for the report.
- Modify as needed to include or exclude fields.
9. Save the Report with a Timestamp#
1
| Export-Csv -Path ("C:\365_reports\StaffMailboxStatistics_" + (Get-Date -Format "yyyyMMdd") + ".csv") -NoTypeInformation
|
- Saves the final report as a CSV file.
- Modify the path if needed.
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! 🚀