Generate Empty Microsoft 365 Groups (Excluding Teams) Report Using Graph PowerShell

Over time, Microsoft 365 tenants accumulate unused groups created for short-term projects, accidental provisioning, or abandoned collaboration setups. Empty Microsoft 365 groups (Unified groups) clutter your directory, complicate governance, and may even lead to access confusion during audits.

This Graph PowerShell script helps administrators identify empty Microsoft 365 groups that are not Teams-enabled, generate a structured report, and email the results automatically for review and cleanup.

🚀 Community Edition Released!

Try the M365Corner Microsoft 365 Reporting Tool — your DIY pack with 20+ out-of-the-box M365 reports for Users, Groups, and Teams.


i) The Script

Connect-MgGraph -Scopes "Group.Read.All", "GroupMember.Read.All", "Mail.Send"
$AdminUPN = "admin@yourtenant.onmicrosoft.com"
$unifiedGroups = Get-MgGroup -All -Property Id, DisplayName, Mail, GroupTypes, CreatedDateTime, ResourceProvisioningOptions |
Where-Object {
$_.GroupTypes -contains "Unified" -and
($_.ResourceProvisioningOptions -notcontains "Team")
}
Write-Host "`nChecking each Microsoft 365 Group (excluding Teams) for members..." -ForegroundColor Cyan

$emptyUnifiedGroups = foreach ($group in $unifiedGroups) {
    $members = Get-MgGroupMember -GroupId $group.Id -ErrorAction SilentlyContinue
    if (-not $members) {
        [PSCustomObject]@{
            DisplayName = $group.DisplayName
            Mail        = $group.Mail
            GroupId     = $group.Id
            CreatedDate = $group.CreatedDateTime
        }
    }
}

if ($emptyUnifiedGroups) {
    Write-Host "`nEmpty Unified Groups found (excluding Teams):`n" -ForegroundColor Green
    $emptyUnifiedGroups | Format-Table DisplayName, Mail, GroupId, CreatedDate
} else {
    Write-Host "`nNo empty unified groups found." -ForegroundColor Yellow
}

$ReportPath = "$env:TEMP\Empty_M365_Groups_Report.csv"
$emptyUnifiedGroups | Export-Csv -Path $ReportPath -NoTypeInformation -Encoding UTF8

$groupCount = if ($emptyUnifiedGroups) { @($emptyUnifiedGroups).Count } else { 0 }
$Subject = "Empty Microsoft 365 Groups Report (Excluding Teams) — $(Get-Date -Format 'yyyy-MM-dd')"

$Body = @"
Hello Admin,<br><br>
Attached is the <b>Empty Microsoft 365 Groups Report</b> (Unified groups excluding Teams-enabled groups).<br>
Total empty groups found: <b>$groupCount</b><br><br>
Regards,<br>
Graph PowerShell Script
"@

$AttachmentContent = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes($ReportPath))
$Attachments = @(
    @{
        "@odata.type" = "#microsoft.graph.fileAttachment"
        Name          = [System.IO.Path]::GetFileName($ReportPath)
        ContentBytes  = $AttachmentContent
    }
)

$Message = @{
    Message = @{
        Subject = $Subject
        Body    = @{
            ContentType = "HTML"
            Content     = $Body
        }
        ToRecipients = @(
            @{ EmailAddress = @{ Address = $AdminUPN } }
        )
        Attachments = $Attachments
    }
    SaveToSentItems = "true"
}
Send-MgUserMail -UserId $AdminUPN -BodyParameter $Message
Write-Host "Empty M365 groups report emailed successfully to $AdminUPN" -ForegroundColor Green
                                

ii) How the Script Works

  1. Connects to Microsoft Graph
  2. The script signs in using these delegated permissions:

    • Group.Read.All → to list Microsoft 365 groups
    • GroupMember.Read.All → to retrieve members of each group
    • Mail.Send → to email the final report
  3. Fetches Unified Groups Excluding Teams
  4. It retrieves all groups and filters to include only:

    • Groups with GroupTypes = Unified (Microsoft 365 Groups)
    • Groups where ResourceProvisioningOptions does not include "Team" (not Teams-enabled)

    This ensures the script targets only standalone M365 groups.

  5. Checks Each Group for Membership
  6. For each unified group, the script calls:

    Get-MgGroupMember -GroupId <id>

    If the call returns no members, the group is tagged as empty and added to the report.

  7. Builds a Structured Output
  8. Each empty group is captured with:

    • DisplayName
    • Mail
    • GroupId
    • CreatedDateTime

    The report is displayed in the console too, for quick visibility.

  9. Exports to CSV and Emails It
  10. The report is exported to a CSV file in the system temp folder, Base64-encoded, and emailed to the administrator using Send-MgUserMail.

    This gives admins a ready-to-review file without manual exporting.


iii) Further Enhancements

You can extend this script to provide even stronger governance:

  • Include Owner Count
  • Fetch owners and add a column:

    • Owner Count
    • Owner Names / UPNs
  • Add Group Age Filter
  • Only report empty groups older than X days (e.g., 30 or 90 days).

  • Auto-tag for Cleanup
  • Automatically apply a naming prefix like “ToDelete” for review workflows.

  • Export to SharePoint / OneDrive
  • Archive empty group reports for yes/no cleanup decisions.

  • Add Member Type Breakdown
  • Flag if a group has:

    • Guests only
    • Members only
    • No owners + no members (highest risk)

iv) Possible Errors & Solutions

Error Cause Solution
Insufficient privileges Missing required Graph permissions. Ensure these scopes are present and consented:
  • Group.Read.All
  • GroupMember.Read.All
  • Mail.Send
Empty results even when empty groups exist Permission scope not applied correctly, or Graph throttling. Reconnect with scopes and retry.
Send-MgUserMail fails Admin UPN isn’t a mailbox-enabled account. Use a licensed mailbox account for $AdminUPN.
CSV attachment is blank No empty M365 groups found. That’s expected behavior; confirm by checking in Entra Admin Center.


v) Conclusion

This script provides a practical and automated way to identify unused Microsoft 365 groups that are not Teams-enabled and have zero members. By emailing the report automatically, it helps administrators keep the tenant clean, audit-friendly, and manageable.

Regularly running this report improves governance, reduces directory clutter, and ensures unused collaboration objects don’t pile up unnoticed.


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