🔧 New: User Management Graph PowerShell Toolkit

Simplify user tasks like bulk creation, updates, password resets, deletions, license checks & more — all from one place.

🚀 Launch Toolkit

Email Archived Teams Report Using Graph PowerShell

When 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.


i) Script

# ===== 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
                            

ii) How the Script Works

  1. Connects to Microsoft Graph
  2. The script connects with the necessary scopes:

    • Group.Read.All to query Microsoft 365 groups that back Teams.
    • Team.ReadBasic.All to read the archived status.
    • Mail.Send to send the CSV by email.
  3. Fetches Teams-enabled groups
  4. Uses Get-MgGroup with the resourceProvisioningOptions filter to list groups that are Teams.

  5. Checks archive status
  6. For each group, it queries the corresponding Team resource with Get-MgTeam and checks if IsArchived is true.

  7. Builds a report
  8. Captures TeamId, TeamName, Description, Visibility, CreatedDate, and IsArchived for each archived Team.

  9. Exports and emails
  10. The report is saved to a timestamped CSV file and sent to the administrator with an HTML summary.


iii) Further Enhancements

  • Include Owners: Add Team owners for accountability.
  • Member Count: Show how many members are in each archived Team.
  • Age Analysis: Flag archived Teams older than one year for potential deletion.
  • Scheduled Reporting: Automate weekly or monthly runs using Task Scheduler or Azure Automation.
  • Lifecycle Actions: Extend the script to notify owners of long-archived Teams.

iv) Use Cases

  • Tenant Cleanup: Identify archived Teams that could be deleted to save space.
  • Governance Reporting: Maintain compliance by documenting which Teams are archived.
  • Audit Preparation: Provide clear visibility into inactive Teams during security reviews.
  • Lifecycle Management: Track when Teams were archived and assess if they should be retired permanently.

v) Possible Errors & Solutions

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.

vi) Conclusion

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.


Graph PowerShell Explorer Widget

20 Graph PowerShell cmdlets with easily accessible "working" examples.


Permission Required

Example:


                


                


                

© m365corner.com. All Rights Reserved. Design by HTML Codex