<# .SYNOPSIS Export complete inventory of distribution groups with members and settings .DESCRIPTION Documents all distribution groups including members, owners, email addresses, and key settings. Useful for migration planning, documentation, or backup. .PARAMETER OutputFolder Destination folder for reports. Default: .\DistributionGroups- .PARAMETER IncludeMembers Include detailed member lists (default: $true, can be slow) .PARAMETER GroupFilter Optional filter for specific groups (default: all) .NOTES ⚠️ AI-GENERATED SCRIPT - UNTESTED This script was generated by Claude AI and has not been tested in production. Review and test thoroughly in a non-production environment before use. - Run in Exchange Management Shell with appropriate RBAC permissions - Large environments may take significant time - Includes both Distribution Groups and Mail-Enabled Security Groups .EXAMPLE .\Export-DistributionGroups.ps1 .EXAMPLE .\Export-DistributionGroups.ps1 -GroupFilter "Sales*" -OutputFolder "D:\Reports\Groups" #> [CmdletBinding()] param( [string]$OutputFolder = (Join-Path -Path (Get-Location) -ChildPath ("DistributionGroups-" + (Get-Date -Format "yyyyMMdd-HHmm"))), [bool]$IncludeMembers = $true, [string]$GroupFilter = "*" ) function NowTag { (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") } Write-Host "[$(NowTag)] ⚠️ AI-GENERATED SCRIPT - UNTESTED" -ForegroundColor Yellow Write-Host "[$(NowTag)] Starting distribution group export..." -ForegroundColor Green # Create output folder New-Item -ItemType Directory -Path $OutputFolder -Force | Out-Null # Get distribution groups Write-Host "[$(NowTag)] Retrieving distribution groups..." $groups = Get-DistributionGroup -Filter "Name -like '$GroupFilter'" -ResultSize Unlimited -ErrorAction SilentlyContinue $groupCount = ($groups | Measure-Object).Count Write-Host "[$(NowTag)] Found $groupCount distribution groups" if ($groupCount -eq 0) { Write-Host "[$(NowTag)] No groups found matching filter: $GroupFilter" -ForegroundColor Yellow exit } # Collect group details $groupDetails = @() $groupMembers = @() $current = 0 foreach ($group in $groups) { $current++ $pct = [int](($current / $groupCount) * 100) Write-Progress -Activity "Processing Distribution Groups" -Status "Processing $($group.Name) ($current/$groupCount)" -PercentComplete $pct # Get managed by $managedByList = @() if ($group.ManagedBy) { foreach ($mgr in $group.ManagedBy) { try { $mgrObj = Get-Recipient $mgr -ErrorAction SilentlyContinue if ($mgrObj) { $managedByList += $mgrObj.PrimarySmtpAddress } } catch {} } } # Get email addresses $emailAddresses = ($group.EmailAddresses | Where-Object { $_ -like "smtp:*" }) -join "; " # Get member count $memberCount = 0 try { $members = Get-DistributionGroupMember -Identity $group.Identity -ResultSize Unlimited -ErrorAction SilentlyContinue $memberCount = ($members | Measure-Object).Count # Collect member details if requested if ($IncludeMembers -and $members) { foreach ($member in $members) { $groupMembers += [PSCustomObject]@{ GroupName = $group.Name GroupPrimarySmtp = $group.PrimarySmtpAddress MemberName = $member.Name MemberPrimarySmtp = $member.PrimarySmtpAddress MemberType = $member.RecipientType } } } } catch { Write-Host "[$(NowTag)] WARNING: Could not get members for $($group.Name)" -ForegroundColor Yellow } $groupDetails += [PSCustomObject]@{ Name = $group.Name DisplayName = $group.DisplayName Alias = $group.Alias PrimarySmtpAddress = $group.PrimarySmtpAddress EmailAddresses = $emailAddresses RecipientTypeDetails = $group.RecipientTypeDetails MemberCount = $memberCount ManagedBy = ($managedByList -join "; ") RequireSenderAuthentication = $group.RequireSenderAuthenticationEnabled HiddenFromAddressLists = $group.HiddenFromAddressListsEnabled ModerationEnabled = $group.ModerationEnabled SendModerationNotifications = $group.SendModerationNotifications AcceptMessagesOnlyFrom = (($group.AcceptMessagesOnlyFrom | ForEach-Object { $_.ToString() }) -join "; ") RejectMessagesFrom = (($group.RejectMessagesFrom | ForEach-Object { $_.ToString() }) -join "; ") BypassModerationFromSenders = (($group.BypassModerationFromSendersOrMembers | ForEach-Object { $_.ToString() }) -join "; ") WhenCreated = $group.WhenCreated WhenChanged = $group.WhenChanged OrganizationalUnit = $group.OrganizationalUnit } } Write-Progress -Activity "Processing Distribution Groups" -Completed # Export results Write-Host "[$(NowTag)] Exporting results..." $groupsFile = Join-Path $OutputFolder "DistributionGroups.csv" $groupDetails | Sort-Object Name | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $groupsFile Write-Host "[$(NowTag)] Groups exported: $groupsFile" -ForegroundColor Green if ($IncludeMembers -and $groupMembers.Count -gt 0) { $membersFile = Join-Path $OutputFolder "DistributionGroup-Members.csv" $groupMembers | Sort-Object GroupName, MemberName | Export-Csv -NoTypeInformation -Encoding UTF8 -Path $membersFile Write-Host "[$(NowTag)] Members exported: $membersFile" -ForegroundColor Green } # Summary Write-Host "`nSUMMARY:" -ForegroundColor Cyan Write-Host " Total Groups: $groupCount" Write-Host " Total Members: $($groupMembers.Count)" Write-Host " Hidden from Address Lists: $(($groupDetails | Where-Object HiddenFromAddressLists).Count)" Write-Host " Moderation Enabled: $(($groupDetails | Where-Object ModerationEnabled).Count)" Write-Host " Security Groups: $(($groupDetails | Where-Object { $_.RecipientTypeDetails -like '*Security*' }).Count)" # Top 10 largest groups $top10 = $groupDetails | Sort-Object MemberCount -Descending | Select-Object -First 10 if ($top10) { Write-Host "`nTop 10 Largest Groups:" -ForegroundColor Cyan $top10 | ForEach-Object { Write-Host " $($_.Name): $($_.MemberCount) members" } } Write-Host "`n[$(NowTag)] Export complete! Output folder: $OutputFolder"