In the past I wrote a script that would cleanup Distribution Lists in Exchange 2010. My original post can be found HERE. In the newest version I’ve changed the ‘Get-TransportServer’ and replaced it with ‘Get-TransportService’ as Microsoft has deprecated ‘Get-TransportServer’ in Exchange 2013/2016. I’ve also cleaned up the code, put more comments in and added a variable table to make modifying this script a bit easier. Other than that it operates like the Exchange Server 2010 version of the script.
NOTES
There will be an Office 365 version coming soon that will scan Office 365 as well as your Hybrid server for mail traffic to distribution lists. This script will also run the same sort of process of marking the CustomAttribute10 to keep track of active/inactive groups. Look for it this week.
Second, and more importantly, I have not added support for Dynamic Distribution groups. Only groups that can be found via ‘Get-DistributionGroup’ are included at this time. The plan is to add that feature, but is on the backburner until I get the Office 365 version of the script completed.
Source Code
I’ve posted the code here and on the TechNet Gallery for you to download and use.–> Download Link
<# .SYNOPSIS Distribution Group Cleanup Script - for Exchange 2013 and 2016 .DESCRIPTION This script will cleanup all distribution lists that have not been used within a certain timeframe. .NOTES Version : 1.1 Date Created : 05/02/2016 Change Log : 1.1 - Change 'GetTransportServer' to 'Get-TransportService' and added a variable list for $To, $From and $SMTPServer : 1.0 - Script first set up Wish list : HTML Report to IT? Rights Required : Local admin on server Sched Task Req'd : No Exchange Version : 2013 / 2016 Author : Damian Scoles Dedicated Blog : http://justaucguy.wordpress.com/ Disclaimer : You are on your own. This was not written by, support by, or endorsed by Microsoft. Code stolen from : None .EXAMPLE .\Run-DistributionGroupCleanup.ps1 To be run once per month as a recurring task .INPUTS None. You cannot pipe objects to this script. #> # Global variable section # Testing Dates - use this for finding older results # $onemonth = ((get-date).addmonths(-13)) # $current = ((get-date).addmonths(-12)) # Production Dates $current = get-date $onemonth = ((get-date).addmonths(-1)) # Arrays $activegroups2 = @() $activegroups = @() $inactivegroups = @() $allgroups = @() $smtp = @() # Other Variables - below are samples, make sure to change for your environment $from = "Notifications@16-lg.local" $SMTPServer = "192.168.0.190" $to = "damian@16-lg.local" $AdminAddress = "damian@16-lg.local" # Load AD Module for PowerShell import-module activedirectory function mail-managerhidden ($groupsmtpaddress) { $manager = ((get-distributiongroup $groupsmtpaddress).managedby) $manager | foreach { $mgr = $_.name $smtp4 = (get-mailbox $mgr).emailaddresses $smtp4 | foreach { $smtp3 = $_.smtpaddress $smtp3 } $smtp += @($smtp3) } $DLName = (get-distributiongroup $groupsmtpaddress).displayname [string] $body = "<strong>NOTIFICATION</strong><BR><BR>As a part of regular maintanence, IT has decided to monitor the usage of Distribution # Lists.<BR><BR>This email is a notification that an Email Distribution Group that you manage has been inactive for 6 months. Because of this level of inactivity, the group has been hidden from the Global Address List. Please check this list to see if it is still valid or not.<BR><BR>Please send an email to $AdminAddress if the list is no longer needed. Thanks for you assistance with this matter." foreach ($line in $smtp) { $messageParameters = @{ Subject = "Distribution Group Manager Alert - Inactive Distribution Group - $DLName" Body = $body From = "$from" To = $line SmtpServer = "$SMTPServer" } Send-MailMessage @messageParameters –BodyAsHtml } } function mail-managerdisabled ($groupsmtpaddress) { $manager = ((get-distributiongroup $groupsmtpaddress).managedby) $manager | foreach { $mgr = $_.name $smtp2 = (get-mailbox $mgr).emailaddresses $smtp2 | foreach { $smtp3 = $_.smtpaddress } $smtp += @($smtp3) } $DLName = (get-distributiongroup $groupsmtpaddress).displayname [string] $body = "<strong>NOTIFICATION</strong><BR><BR>As a part of regular maintanence, IT has decided to monitor the usage of Distribution # Lists.<BR><BR>This email is a notification that an Email Distribution Group that you manage has been inactive for over 12 months. This Distribiution group has been deleted.<BR><BR>Please send an email to $AdminAddress if you have any questions. Thanks for you assistance with this matter." foreach ($line in $smtp) { $messageParameters = @{ Subject = "Distribution Group Manager Alert - Removed Distribution Group - $DLName" Body = $body From = "$from" To = $line SmtpServer = "$SMTPServer" } Send-MailMessage @messageParameters –BodyAsHtml } } function emailIT-Groupremoval ($groupsmtpaddress) { $DLName = (get-distributiongroup $groupsmtpaddress).displayname [string] $body = "<strong>NOTIFICATION</strong><BR><BR>As a part of regular maintanence this group was disabled. The group has been inactive for 12 months per the DL Cleanup Script. Confirm that this list can be deleted and remove it from AD." $messageParameters = @{ Subject = "Distribution Group - IT Alert - Removed Distribution Group - $DLName" Body = $body From = "$from" to = "$to" SmtpServer = "$SMTPServer" } Send-MailMessage @messageParameters –BodyAsHtml } # Get a list of the active groups $servers = get-transportservice foreach ($name in $servers) { $activegroups2 += (Get-MessageTrackingLog -Server $name.name -EventId Expand -ResultSize Unlimited -start $onemonth -end $current | Sort-Object RelatedRecipientAddress | Group-Object RelatedRecipientAddress | Sort-Object Name | select-object name) } $activegroups2 = $activegroups2 | sort-object name | group-object name foreach ($line in $activegroups2) { $activegroups += $line.name } # Get a list of all groups $allgroups2 = get-distributiongroup -resultsize unlimited | Select-Object -Property @{Label="Name";Expression={$_.PrimarySmtpAddress}} foreach ($line in $allgroups2) { $allgroups += $line.name } # Find inactive groups by comparing active groups to all groups $InactiveGroups2 = Compare-Object $activegroups $allgroups foreach ($line in $inactivegroups2) { $smtp2=$line.inputobject $address=$smtp2.local+"@"+$smtp2.domain $inactivegroups += $address } # Set custom attribute 10 for active groups to 0 foreach ($line in $ActiveGroups){ set-distributiongroup -identity $line -CustomAttribute10 0 -warningaction silentlycontinue } # Set custom attribute 10 for inactive groups - increase by 1 # Hide or disable group foreach ($line in $InactiveGroups){ [string]$email = $line [int]$number = (get-distributiongroup -identity $email).CustomAttribute10 $number += 1 set-distributiongroup -identity $email -CustomAttribute10 $number if ($number -eq 6) { $notes = "$current - Hidden from address list due to inactive use." Set-Group -identity $email -notes $notes Set-DistributionGroup -identity $email -HiddenFromAddressListsEnabled $true # Email manager - group hidden mail-managerhidden $email } if ($number -eq 12) { # Email manager and IT of group removal mail-managerdisabled $email emailIT-Groupremoval $email # Disable the group $notes = "$current - No longer Mail Enabled due to inactive use." Set-Group -identity $email -notes $notes Disable-DistributionGroup -identity $email -Confirm:$false } }
Hey, the description in the beginning of the script is wrong. It says ” This script will cleanup all SCRIPTS that have not been used within a certain timeframe.”
Also, in the synopsis it says “Exchange 203” 🙂
Fixed. Thanks for noticing this.