Microsoft Teams makes collaboration with external users easy—but that convenience also introduces governance and security challenges. Guest users can access conversations, files, and shared resources, and over time administrators may lose visibility into which Teams include guests and whether those Teams are properly owned.
A common gap in many tenants is the lack of a consolidated view answering:
This Graph PowerShell script focuses exclusively on Teams-backed Microsoft 365 groups, identifies Teams that contain guest users, generates a governance-ready report, and automatically emails it to administrators—without requiring any SMTP configuration.
Try the M365Corner Microsoft 365 Reporting Tool — your DIY pack with 20+ out-of-the-box M365 reports for Users, Groups, and Teams.
$SenderUPN = (Get-MgContext).Account
$Recipients = @(
"admin@yourtenant.onmicrosoft.com",
"securityteam@yourtenant.onmicrosoft.com"
)
Connect-MgGraph -Scopes "Group.Read.All","User.Read.All","Directory.Read.All","Mail.Send"
$TeamsEnabledGroups = Get-MgGroup -All `
-Property Id,DisplayName,Mail,GroupTypes,ResourceProvisioningOptions,CreatedDateTime |
Where-Object {
$_.GroupTypes -contains "Unified" -and
$_.ResourceProvisioningOptions -contains "Team"
}
$Report = @()
foreach ($group in $TeamsEnabledGroups) {
try {
$Members = Get-MgGroupMember -GroupId $group.Id -All
$Owners = Get-MgGroupOwner -GroupId $group.Id -All
} catch {
continue
}
$GuestCount = 0
foreach ($member in $Members) {
if ($member.AdditionalProperties.'@odata.type' -ne "#microsoft.graph.user") {
continue
}
try {
$User = Get-MgUser -UserId $member.Id -Property UserType
} catch {
continue
}
if ($User.UserType -eq "Guest") {
$GuestCount++
}
}
if ($GuestCount -gt 0) {
$Report += [PSCustomObject]@{
"Team Name" = $group.DisplayName
"Team Email" = $group.Mail
"Team Id" = $group.Id
"Created Date" = $group.CreatedDateTime
"Guest Count" = $GuestCount
"Owner Count" = $Owners.Count
"Has Owners" = if ($Owners.Count -gt 0) { "Yes" } else { "No" }
}
}
}
$ReportPath = "$env:TEMP\Teams_With_Guest_Users_Report.csv"
if ($Report.Count -gt 0) {
$Report | Sort-Object "Guest Count" -Descending |
Export-Csv -Path $ReportPath -NoTypeInformation -Encoding utf8
} else {
"No Teams (Teams-enabled groups) with guest users were found." |
Set-Content -Path $ReportPath -Encoding utf8
}
$Bytes = [System.IO.File]::ReadAllBytes($ReportPath)
$Utf8Bom = New-Object System.Text.UTF8Encoding($true)
[System.IO.File]::WriteAllText(
$ReportPath,
[System.Text.Encoding]::UTF8.GetString($Bytes),
$Utf8Bom
)
$Count = $Report.Count
$Subject = "Teams with Guest Users — $(Get-Date -Format 'yyyy-MM-dd')"
$Body = @"
Hello Team,<br><br>
Attached is the <b>Teams with Guest Users</b> report.<br>
This report includes only <b>Teams-enabled Microsoft 365 Groups</b> that contain guest users, along with guest and owner counts.<br><br>
Total Teams with guests found: <b>$Count</b><br><br>
Regards,<br>
Graph PowerShell Automation
"@
$AttachmentContent = [System.Convert]::ToBase64String(
[System.IO.File]::ReadAllBytes($ReportPath)
)
$Attachments = @(
@{
"@odata.type" = "#microsoft.graph.fileAttachment"
Name = "Teams_With_Guest_Users_Report.csv"
ContentBytes = $AttachmentContent
}
)
$ToRecipients = $Recipients | ForEach-Object {
@{ EmailAddress = @{ Address = $_ } }
}
$Message = @{
Message = @{
Subject = $Subject
Body = @{
ContentType = "HTML"
Content = $Body
}
ToRecipients = $ToRecipients
Attachments = $Attachments
}
SaveToSentItems = "true"
}
Send-MgUserMail -UserId $SenderUPN -BodyParameter $Message
| Error | Cause | Solution |
|---|---|---|
| Report shows no Teams despite known guest access | Guest detection using group member metadata alone | Script correctly resolves full user objects to read UserType |
| 403 Access Denied when sending mail | Sender does not match signed-in account or missing Mail.Send | Use (Get-MgContext).Account and grant delegated consent |
| Performance impact in large tenants | Per-user lookups for accurate guest detection | Run off-hours or schedule periodically for governance checks |
| CSV opens without headers in Excel | Missing UTF-8 BOM | Explicit BOM handling already implemented in the script |
Teams with guest users represent a critical intersection of collaboration and security. Without visibility, external access can persist unchecked and unmanaged. This Graph PowerShell solution provides administrators with a clear, automated way to identify Teams containing guest users, verify ownership accountability, and maintain control over external collaboration.
By combining accurate guest detection with automated reporting and SMTP-less email delivery, this script fits seamlessly into modern Microsoft 365 governance workflows.
© m365corner.com. All Rights Reserved. Design by HTML Codex