Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.
🚀 Launch ToolkitIf you manage Microsoft 365, “How big are our mailboxes?” and “Who’s not using email?” are questions you hear a lot. In this guide, you’ll learn how to export tenant-wide Mailbox Usage Detail using Microsoft Graph PowerShell—with guardrails, clean examples, and practical tips you can reuse for monthly reporting.
A CSV containing per-mailbox stats (varies by date), such as:
Think of it as your single source for mailbox growth, cleanup candidates, and license optimization.
# Requires PowerShell 7+ recommended
Install-Module Microsoft.Graph -Scope CurrentUser
Update-Module Microsoft.Graph
Connect-MgGraph -Scopes "Reports.Read.All"
Select-MgProfile -Name "beta" # If the cmdlet lives in beta for your tenant; otherwise keep v1.0
Tip: If consent prompts appear, you’ll need an admin to approve Reports.Read.All.
Get-MgReportMailboxUsageDetail -Period <String> -OutFile <String>
Get-MgReportMailboxUsageDetail -Period "D7" -OutFile ".\MailboxUsage_D7.csv"
Get-MgReportMailboxUsageDetail -Period "D30" -OutFile ".\MailboxUsage_D30.csv"
Get-MgReportMailboxUsageDetail -Period "D90" -OutFile ".\MailboxUsage_D90.csv"
Get-MgReportMailboxUsageDetail -Period "D180" -OutFile ".\MailboxUsage_D180.csv"
Open the CSV quickly from PowerShell: Import-Csv .\MailboxUsage_D30.csv | Out-GridView
$data = Import-Csv .\MailboxUsage_D30.csv
$inactive = $data | Where-Object { $_.LastActivityDate -eq $null -or [datetime]::TryParse($_.LastActivityDate, [ref]([datetime]$null)) -eq $false }
$inactive | Select-Object DisplayName,UserPrincipalName,LastActivityDate | Out-GridView
$data = Import-Csv .\MailboxUsage_D30.csv
$data | Sort-Object {[double]$_.StorageUsedInMB} -Descending |
Select-Object DisplayName,UserPrincipalName,@{n='StorageGB';e={[math]::Round(([double]$_.StorageUsedInMB/1024),2)}} -First 20 |
Out-GridView
Export D30 and D90 and Compare last activity and storage:
$d30 = Import-Csv .\MailboxUsage_D30.csv
$d90 = Import-Csv .\MailboxUsage_D90.csv
$join = $d30 | ForEach-Object {
$p = $_
$older = $d90 | Where-Object { $_.UserPrincipalName -eq $p.UserPrincipalName } | Select-Object -First 1
if ($older) {
[pscustomobject]@{
DisplayName = $p.DisplayName
UserPrincipalName = $p.UserPrincipalName
StorageGB_New = [math]::Round(([double]$p.StorageUsedInMB/1024),2)
StorageGB_Old = [math]::Round(([double]$older.StorageUsedInMB/1024),2)
GrowthGB = [math]::Round((([double]$p.StorageUsedInMB - [double]$older.StorageUsedInMB)/1024),2)
}
}
}
$join | Sort-Object GrowthGB -Descending | Out-GridView
Export D7, D30, D90, and D180, then:
$upn = "user@contoso.com"
$files = ".\MailboxUsage_D7.csv",".\MailboxUsage_D30.csv",".\MailboxUsage_D90.csv",".\MailboxUsage_D180.csv"
$trend = foreach ($f in $files) {
if (Test-Path $f) {
Import-Csv $f | Where-Object { $_.UserPrincipalName -eq $upn } |
Select-Object @{n='Period';e={[System.IO.Path]::GetFileNameWithoutExtension($f)}},
DisplayName,UserPrincipalName,
@{n='StorageGB';e={[math]::Round(([double]$_.StorageUsedInMB/1024),2)}},
LastActivityDate
}
}
$trend | Format-Table -AutoSize
| Error | Cause | Solution |
|---|---|---|
| Period is out of allowed range | Value > 180 days (e.g., D270). | Value > 180 days (e.g., D270). Use D7, D30, D90, or D180. Stick to ≤ 180. |
| Insufficient privileges to complete the operation | Missing Reports.Read.All consent. | Reconnect with Connect-MgGraph -Scopes "Reports.Read.All" and have an admin approve if prompted. |
| Access denied / Forbidden | Conditional Access / MFA / admin restrictions. | Confirm your account’s access policy, try an admin account, or use an approved device/location. |
| CSV empty or missing expected columns | Exported for a period with sparse activity, or tenant replica delay. | Try a longer period like D30/D90. Re-run after a short interval if service data is catching up. |
With Get-MgReportMailboxUsageDetail, you can generate a clean, exportable view of mailbox activity and storage in minutes—perfect for monthly reports, audits, or quick health checks. Start small with D7, scale to D180, and keep your CSVs versioned so trends pop right out.
Did You Know? Managing Microsoft 365 applications is even easier with automation. Try our Graph PowerShell scripts to automate tasks like generating reports, cleaning up inactive Teams, or assigning licenses efficiently.
Ready to get the most out of Microsoft 365 tools? Explore our free Microsoft 365 administration tools to simplify your administrative tasks and boost productivity.
© Your Site Name. All Rights Reserved. Design by HTML Codex