🔧 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 Private Archived Teams Report Using Graph PowerShell

In large Microsoft Teams environments, administrators often archive inactive private teams to maintain workspace hygiene and reduce clutter. However, keeping track of which private teams are archived can quickly become a challenge. This Graph PowerShell script automates the process — fetching all private archived Teams, generating a detailed report, and emailing it directly to the administrator.


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   = "Private Archived Teams Report"
$CsvOutDir = "$env:TEMP"

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

$privateArchived = @()

foreach ($g in $teamsGroups) {
    if ($g.Visibility -ne "Private") { 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 }
        }

        $privateArchived += [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 ("Private_Archived_Teams_{0}.csv" -f $ts)
$privateArchived | Sort-Object DisplayName | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $csvPath

$total = $privateArchived.Count
$summaryHtml = @"
<html>
  <body style='font-family:Segoe UI,Arial,sans-serif'>
    <h3>Private Archived Teams Report</h3>
    <p>Total private 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. Connection & Permissions:
  2. The script connects to Microsoft Graph using the required scopes — Group.Read.All, Team.ReadBasic.All, and Mail.Send — to access Teams data and send mail.

  3. Fetches Teams:
  4. It retrieves all Microsoft 365 groups with Teams provisioned using the resourceProvisioningOptions filter.

  5. Filters Private & Archived Teams:
  6. The script checks for Teams with Visibility set to Private and IsArchived equal to True.

  7. Gathers Owner Information:
  8. For each archived team, it fetches owner details, including their display names and email addresses.

  9. Generates and Emails Report:
  10. A CSV file is created in the temp directory containing the details. The script then composes a brief HTML email with the CSV attached and sends it to the administrators listed in $ToList.


iii) Further Enhancements

  • Include team member counts to assess engagement before archiving.
  • Add last activity date from Teams usage reports for richer insights.
  • Integrate with SharePoint or Power BI for centralized visualization.
  • Schedule automated runs via Azure Automation for periodic reports.
  • Extend script to auto-notify team owners before archival actions.

iv) Possible Errors and Solutions

Error Cause Solution
Access Denied Insufficient Graph permissions Use Connect-MgGraph -Scopes "Group.Read.All, Team.ReadBasic.All, Mail.Send"
Empty CSV File No private archived teams found Verify if any private teams have been archived in your tenant.
Request_UnsupportedQuery Query syntax issue Ensure the resourceProvisioningOptions filter syntax matches the Graph schema.
Send-MgUserMail fails Sender lacks mailbox Make sure $FromUser is a licensed mailbox-enabled account.
Owners missing Owners not assigned Encourage ownership assignment before archiving to avoid orphaned Teams.

v) Conclusion

This Graph PowerShell script offers administrators a streamlined approach to monitor and report archived private Teams in Microsoft 365. Automating this task helps maintain governance, ensures compliance readiness, and simplifies lifecycle management. By emailing the report directly to stakeholders, it keeps IT teams informed and proactive about workspace hygiene.


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