Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.
🚀 Launch ToolkitWhen Teams are no longer needed, administrators can archive them to preserve content but stop new activity. Over time, your tenant may accumulate many archived Teams—some intentionally preserved for record-keeping, others forgotten in the shuffle of projects. Without visibility into which Teams are archived, it becomes difficult to manage tenant health, storage, and governance.
This Graph PowerShell script gives you a clear report of all archived Teams, complete with details like TeamId, DisplayName, Description, Visibility, CreatedDate, and IsArchived. It exports the data to a CSV file and emails the report to the administrator for easy tracking and audits.
# ===== Archived Microsoft Teams -> CSV -> Email to Admin =====
# Requires: Microsoft.Graph module
# Scopes: Group.Read.All, Team.ReadBasic.All, Mail.Send
# --- Email variables ---
$FromUser = "admin@contoso.com" # Sender (must have mailbox)
$To = "it-ops@contoso.com" # Recipient
$Subject = "Archived Microsoft Teams report"
$CsvOutDir = "$env:TEMP"
# --- Connect to Microsoft Graph ---
Import-Module Microsoft.Graph -ErrorAction Stop
Connect-MgGraph -Scopes "Group.Read.All","Team.ReadBasic.All","Mail.Send"
# --- Get Teams-enabled groups (Microsoft 365 groups that back Teams) ---
$teamsGroups = Get-MgGroup -All -Filter "resourceProvisioningOptions/Any(x:x eq 'Team')" `
-Property "id,displayName,description,visibility,createdDateTime,mailNickname"
# --- Build rows only for archived Teams ---
$rows = @()
foreach ($g in $teamsGroups) {
try {
# Fetch the Team resource to read IsArchived
$team = Get-MgTeam -TeamId $g.Id -ErrorAction Stop
if ($team.IsArchived -eq $true) {
$rows += [PSCustomObject]@{
TeamId = $g.Id
TeamName = $g.DisplayName
Description = $g.Description
Visibility = $g.Visibility
CreatedDate = $g.CreatedDateTime
IsArchived = $team.IsArchived
}
}
} catch {
# If team fetch fails (e.g., recently deleted/team not fully provisioned), skip gracefully
}
}
# --- Export to CSV ---
if (-not (Test-Path -Path $CsvOutDir)) { New-Item -ItemType Directory -Path $CsvOutDir | Out-Null }
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
$csvPath = Join-Path $CsvOutDir ("Archived_Teams_{0}.csv" -f $ts)
$rows | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
# --- Prepare HTML Body ---
$totalTeams = $teamsGroups.Count
$totalArchived = $rows.Count
$summaryHtml = @"
<html>
<body style='font-family:Segoe UI,Arial,sans-serif'>
<h3>Archived Microsoft Teams Report</h3>
<p>Total Teams scanned: <b>$totalTeams</b></p>
<p>Total archived Teams: <b>$totalArchived</b></p>
<p>The full list (with TeamId, Name, Visibility, CreatedDate) is attached as a CSV.</p>
</body>
</html>
"@
# --- Prepare Attachment ---
$fileBytes = [System.IO.File]::ReadAllBytes($csvPath)
$base64Content = [System.Convert]::ToBase64String($fileBytes)
$csvFileName = [System.IO.Path]::GetFileName($csvPath)
$attachment = @{
"@odata.type" = "#microsoft.graph.fileAttachment"
name = $csvFileName
contentBytes = $base64Content
contentType = "text/csv"
}
# --- Prepare and Send Email ---
$mail = @{
message = @{
subject = "${Subject}"
body = @{
contentType = "HTML"
content = $summaryHtml
}
toRecipients = @(@{ emailAddress = @{ address = $To } })
attachments = @($attachment)
}
saveToSentItems = $true
}
Send-MgUserMail -UserId $FromUser -BodyParameter $mail
Write-Host "Done. CSV saved at: $csvPath" -ForegroundColor Green
The script connects with the necessary scopes:
Uses Get-MgGroup with the resourceProvisioningOptions filter to list groups that are Teams.
For each group, it queries the corresponding Team resource with Get-MgTeam and checks if IsArchived is true.
Captures TeamId, TeamName, Description, Visibility, CreatedDate, and IsArchived for each archived Team.
The report is saved to a timestamped CSV file and sent to the administrator with an HTML summary.
Error | Cause | Solution |
---|---|---|
Authorization_RequestDenied | Missing Graph permissions or admin consent | Reconnect with Group.Read.All, Team.ReadBasic.All, and Mail.Send; ensure admin consent is granted. |
Get-MgGroup not recognized | Microsoft Graph module not installed | Install with Install-Module Microsoft.Graph -Scope CurrentUser. |
Script skips some Teams | Some Teams may be deleted or not fully provisioned | Handled by try/catch; verify status manually if needed. |
Email not sent | $FromUser not mailbox-enabled | Use a licensed mailbox-enabled account as sender. |
Empty report | No archived Teams in tenant | Validate by checking Teams in the Teams admin center. |
Archived Teams help preserve history without cluttering active collaboration, but they can pile up and complicate governance. This script gives admins a complete inventory of archived Teams—emailed as a CSV—so you can keep track of which Teams are inactive, when they were created, and what to do next. Automating this reporting ensures better lifecycle management and a healthier Microsoft 365 environment.
© m365corner.com. All Rights Reserved. Design by HTML Codex