Public/Get-DistributionGroupAudit.ps1
|
function Get-DistributionGroupAudit { <# .SYNOPSIS Audits distribution groups for migration planning. .DESCRIPTION Inventories distribution groups, dynamic distribution groups, and mail-enabled security groups with: - Member count - Group type - Managed by - Nested group detection - Empty group detection - External member detection .PARAMETER IncludeEmpty Include groups with zero members. Default excludes them. .EXAMPLE Get-DistributionGroupAudit .EXAMPLE Get-DistributionGroupAudit -IncludeEmpty | Where-Object MemberCount -eq 0 | Export-Csv EmptyGroups.csv #> [CmdletBinding()] param( [switch]$IncludeEmpty ) $results = [System.Collections.Generic.List[PSCustomObject]]::new() # Standard Distribution Groups Write-Verbose "Getting distribution groups..." $distGroups = Get-DistributionGroup -ResultSize Unlimited foreach ($group in $distGroups) { $members = @(Get-DistributionGroupMember -Identity $group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue) $memberCount = $members.Count if (-not $IncludeEmpty -and $memberCount -eq 0) { continue } $nestedGroups = @($members | Where-Object RecipientType -like '*Group*').Count $externalMembers = @($members | Where-Object RecipientType -eq 'MailContact').Count $results.Add([PSCustomObject]@{ Name = $group.DisplayName PrimarySmtp = $group.PrimarySmtpAddress GroupType = if ($group.GroupType -match 'Security') { 'Mail-Enabled Security' } else { 'Distribution' } MemberCount = $memberCount NestedGroups = $nestedGroups ExternalMembers = $externalMembers ManagedBy = ($group.ManagedBy | ForEach-Object { $_.Name }) -join '; ' AcceptFromExternal = -not $group.RequireSenderAuthenticationEnabled Hidden = $group.HiddenFromAddressListsEnabled MigrationNotes = if ($nestedGroups -gt 0) { 'Has nested groups - verify after migration' } elseif ($externalMembers -gt 0) { 'Has external contacts' } else { '' } }) } # Dynamic Distribution Groups Write-Verbose "Getting dynamic distribution groups..." $dynGroups = Get-DynamicDistributionGroup -ResultSize Unlimited -ErrorAction SilentlyContinue foreach ($group in $dynGroups) { $previewMembers = @(Get-Recipient -RecipientPreviewFilter $group.RecipientFilter -ErrorAction SilentlyContinue) $results.Add([PSCustomObject]@{ Name = $group.DisplayName PrimarySmtp = $group.PrimarySmtpAddress GroupType = 'Dynamic' MemberCount = $previewMembers.Count NestedGroups = 0 ExternalMembers = 0 ManagedBy = ($group.ManagedBy | ForEach-Object { $_.Name }) -join '; ' AcceptFromExternal = $false Hidden = $group.HiddenFromAddressListsEnabled MigrationNotes = 'Dynamic group - verify recipient filter works post-migration' }) } $results | Sort-Object GroupType, Name } |