πŸ”§ 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 Public Archived Teams Report Using Graph PowerShell

When managing Microsoft Teams environments, keeping track of archived teams is essential β€” especially public ones that remain visible but inactive. These teams can accumulate over time, leading to clutter, unnecessary data retention, or potential compliance risks. This Graph PowerShell script automatically identifies all public archived Teams within your tenant, generates a detailed report, and emails it to administrators for review or cleanup planning.


i) The Script


Import-Module Microsoft.Graph -ErrorAction Stop
Connect-MgGraph -Scopes "Group.Read.All","Team.ReadBasic.All","Mail.Send"

$FromUser  = "admin@contoso.com"
$ToList    = "it-ops@contoso.com;teams-admin@contoso.com"
$Subject   = "Public Archived Teams Report"
$CsvOutDir = "$env:TEMP"

$teamsGroups = Get-MgGroup -All -Property Id,DisplayName,Visibility,CreatedDateTime,ResourceProvisioningOptions `
  -Filter "resourceProvisioningOptions/Any(x:x eq 'Team')"

$publicArchived = @()

foreach ($g in $teamsGroups) {
    if ($g.Visibility -ne "Public") { continue }
    $team = Get-MgTeam -TeamId $g.Id -ErrorAction SilentlyContinue
    if ($null -ne $team -and $team.IsArchived -eq $true) {
        $ownerObjs = Get-MgGroupOwner -GroupId $g.Id -All -ErrorAction SilentlyContinue
        $ownerNames = @()
        $ownerMails = @()
        foreach ($o in ($ownerObjs | Where-Object { $_ })) {
            $name = $o.AdditionalProperties['displayName']
            $mail = $o.AdditionalProperties['mail']
            if ($name) { $ownerNames += $name }
            if ($mail) { $ownerMails += $mail }
        }

        $publicArchived += [PSCustomObject]@{
            TeamId       = $g.Id
            DisplayName  = $g.DisplayName
            Visibility   = $g.Visibility
            IsArchived   = $team.IsArchived
            CreatedDate  = $g.CreatedDateTime
            Owners       = ($ownerNames -join "; ")
            OwnerEmails  = ($ownerMails -join "; ")
        }
    }
}

if (-not (Test-Path -Path $CsvOutDir)) { New-Item -ItemType Directory -Path $CsvOutDir | Out-Null }
$ts      = Get-Date -Format "yyyyMMdd_HHmmss"
$csvPath = Join-Path $CsvOutDir ("Public_Archived_Teams_{0}.csv" -f $ts)
$publicArchived | Sort-Object DisplayName | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $csvPath

$total = $publicArchived.Count
$summaryHtml = @"
<html>
  <body style='font-family:Segoe UI,Arial,sans-serif'>
    <h3>Public Archived Teams Report</h3>
    <p>Total public archived teams: <b>$total</b></p>
    <p>Attached CSV includes: TeamId, DisplayName, Visibility, IsArchived, CreatedDate, Owners, OwnerEmails.</p>
  </body>
</html>
"@

$fileBytes     = [System.IO.File]::ReadAllBytes($csvPath)
$base64Content = [System.Convert]::ToBase64String($fileBytes)
$attachment    = @{
  "@odata.type" = "#microsoft.graph.fileAttachment"
  name          = [System.IO.Path]::GetFileName($csvPath)
  contentBytes  = $base64Content
  contentType   = "text/csv"
}

$recipients = @()
$ToList.Split(@(';', ','), [System.StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
  $addr = $_.Trim()
  if ($addr) { $recipients += @{ emailAddress = @{ address = $addr } } }
}

$mail = @{
  message = @{
    subject = "$Subject"
    body    = @{ contentType = "HTML"; content = $summaryHtml }
    toRecipients = $recipients
    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 uses the Connect-MgGraph cmdlet with Group.Read.All, Team.ReadBasic.All, and Mail.Send scopes to access Teams and send emails.

  3. Fetches all Teams:
  4. It retrieves all Microsoft 365 Groups provisioned as Teams by filtering on resourceProvisioningOptions.

  5. Filters Public and Archived Teams:
  6. It checks each team’s Visibility and IsArchived properties, selecting only those that are both Public and Archived.

  7. Retrieves Ownership Details:
  8. The script calls Get-MgGroupOwner for each team to list owners and their email addresses.

  9. Exports to CSV:
  10. It compiles the team details β€” including Team ID, Display Name, Visibility, IsArchived status, Created Date, and Owners β€” and exports them to a CSV file in the temp directory.

  11. Emails the Report:
  12. A brief HTML summary is created, and the CSV file is sent as an attachment to designated recipients using Send-MgUserMail.


iii) Further Enhancements

  • Add member count to understand team utilization before archiving decisions.
  • Include last activity date from Teams usage reports for more context.
  • Integrate with Power Automate or Azure Automation to schedule periodic reporting.
  • Automatically unarchive inactive teams after review with a follow-up script.
  • Store reports in SharePoint for centralized access and compliance tracking.

iv) Possible Errors and Solutions

Error Cause Solution
Request_UnsupportedQuery Filter syntax issue Ensure Graph query syntax matches resourceProvisioningOptions/Any(x:x eq 'Team').
Access Denied Missing permissions Reconnect with Group.Read.All, Team.ReadBasic.All, and Mail.Send scopes.
Email not delivered Sender has no mailbox Ensure $FromUser has a valid Exchange mailbox.
Empty CSV No public archived teams found Verify that your tenant actually has archived public teams.
Get-MgTeam returns null Team object may not yet exist or permissions insufficient Wait a few minutes or verify app permissions.

v) Conclusion

This Graph PowerShell script provides administrators with an automated way to identify and report all public archived Teams in the tenant. By regularly running this script, IT admins can keep their environment organized, reclaim storage, and maintain visibility into inactive collaboration spaces. It’s a simple yet effective step toward better Teams lifecycle management in Microsoft 365.


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