Add 12 AI-generated PowerShell scripts with documentation

⚠️ 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>
This commit is contained in:
Martien de Kleijn
2025-10-15 10:52:44 +02:00
parent 5e9d160d48
commit 62134801aa
14 changed files with 2565 additions and 0 deletions

View File

@ -0,0 +1,163 @@
<#
.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"