⚠️ IMPORTANT: These scripts are AI-GENERATED and UNTESTED Exchange Scripts (5): - Get-MailboxPermissions.ps1: Audit delegate access permissions - Get-InactiveMailboxes.ps1: Identify stale mailboxes - Compare-MailboxDatabases.ps1: Database health comparison - Export-DistributionGroups.ps1: Distribution group inventory - Get-MailflowStats.ps1: Transport log analysis Active Directory Scripts (3): - Get-ADUserLastLogon.ps1: True LastLogon across all DCs - Export-OUStructure.ps1: OU hierarchy with GPO links - Compare-ADGroupMemberships.ps1: Compare user group memberships System Maintenance Scripts (4): - Get-ServerInventory.ps1: Hardware/software inventory report - Monitor-DiskSpace.ps1: Disk space monitoring with alerts - Backup-ExchangeCertificates.ps1: Certificate backup to PFX - Test-ExchangeHealth.ps1: Aggregated Exchange health checks Documentation: - Updated CLAUDE.md with AI-generated scripts section - Added AI-GENERATED-SCRIPTS.md with warnings and testing guide All scripts include prominent warnings and follow established patterns from existing scripts. Require thorough testing before production use. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
164 lines
6.5 KiB
PowerShell
164 lines
6.5 KiB
PowerShell
<#
|
|
.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-<date>
|
|
|
|
.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"
|