Rename a distribution group in Exchange with Powershell

Recently I was asked to rename some distribution groups in Exchange. Not so tough of a problem, but painstaking to do one at a time and there were a few of these to do. So I did what any good admin should do, I wrote a script to take care of this.

The issues
To properly rename a distribution group, you need to not only change the name of the group, but also the Alias, DisplayName and entries in the EmailAddresses field. The first two are easy but if you’re like me, you need to add a handful of emailaddresses to these fields. In our environment, we tend to add records when a name is changed rather than swap the old for the new. This way, if someone uses the old address, it still goes to where they want it too. Probably a better answer would be to create a mailbox with the old address and setup an auto reply that says “Hey, use the new address for this list.” That’ll be for another day.

Anyways, here is the script…
I should note, that I’m keeping this function (along with some other Exchange functions on github. you can get the most recent version of this script here: https://github.com/glaisne/PowerShellExchangeFunctions/archive/master.zip

function Rename-DistributionGroup
{

<#
.SYNOPSIS
	Renames distribution groups
.DESCRIPTION
	Changes the old name of the distribution group
    to the new name. Specifically, the fields that
    are changed are 'Name', 'Alias', 'DisplayName'.
    Also, for each smtp domain the added new alias
    address will be added. For example, if the old 
    distribution list had an EmailAddresses field 
    containing smtp:OldName@contoso.com and 
    smtp:OldName@microsoft.com, this cmdlet would 
    add 'smtp:NewName@contoso.com and 
    'smtp:NewName@Microsoft.com.    
.EXAMPLE
	Rename-DistributionGroup -OldName "OldDistributionGroup" -NewName "NewDistribtuionGroup"

    This would rename the distribution group named "OldDistributionGroup" to "NewDistributionGroup"
.PARAMETER OldName
	The old (or current) name of the distribution group
.PARAMETER NewName
    The new name of the distribution group. This is the name
    this script will change the distribution group to.
.Parameter Confirm
    Use this to force or remove confirmation.
#>
	[CmdletBinding(SupportsShouldProcess=$true)]
	param(
		[Parameter(Mandatory=$true)]
		[string]  $OldName,
		[Parameter(Mandatory=$true)]
        [string]  $NewName,
		[Boolean] $Confirm = $True
	)
        
    write-verbose "Fields that contain ""$OldName"""
    try
    {
        Get-DistributionGroup $OldName -ErrorAction "Stop" |fl * | out-string -stream | select-string $OldName | 
        Where {$_ -ne "" } | ForEach { write-verbose $_ }
    }
    catch [System.Management.Automation.RuntimeException]
    {
        Write-Verbose "There was an error accessing Distribution Group $OldName"
	    write-host ("Exception: " + $Error[0].Exception.GetType().FullName)
	    write-host $Error[0].Exception.Message
        return
    }
    catch
    {
        Write-Verbose "There was an error accessing Distribution Group $OldName"
        throw $_
    }
            

    Write-Verbose "Getting the Distribution Group $OldName"
    $group = Get-DistributionGroup $OldName

    if ( $PSCmdlet.ShouldProcess($OldName, "Setting Name, Alias and DisplayName to $NewName") ) 
	{
		if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Setting Name, Alias and DisplayName to $NewName on target $OldName"  )) )
        {
            Set-DistributionGroup $OldName -alias $NewName -DisplayName $NewName -ForceUpgrade 
        }
    }

    Write-Verbose "EmailAddresses listed on the original group:"
    $group.EmailAddresses |ft -auto | out-string -stream | Where {$_ -ne "" } | ForEach { write-verbose $_ }

    foreach ($EmailAddress in $($group.EmailAddresses))
    {
        if ($EmailAddress -notmatch "^smtp:.*@.*$")
        {
            Write-Verbose "Skipping processing of EmailAddress $EmailAddress"
            Continue
        }

        $domain = $EmailAddress.split('@')[1]

        Write-Verbose "Current Emailaddress ($EmailAddress) domain = $Domain"

        Write-Verbose "Adding new smtp address (smtp:$NewName@$Domain) to the EmailAddresses field"
        $group.EmailAddresses += "smtp:$NewName@$Domain"
    }
        
    Get-DistributionGroup $OldName -ErrorAction "Stop" |fl * | out-string -stream | select-string $OldName | 
    Where {$_ -ne "" } | ForEach { write-verbose $_ }

	if ( $PSCmdlet.ShouldProcess($OldName, "Adding new alias to the old address' smtp addresses.") ) 
	{

		if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Adding $NewName addresses on target $OldName"  )) )
        {
            if ($($group.EmailAddressPolicyEnabled))
            {
                Write-Verbose "Turning off the Email Address Policy for this distribution group."
                Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$false
            }
            Write-Verbose "Setting the distribution groups new EmailAddresses setting."
            Set-DistributionGroup $NewName -EmailAddresses $($group.EmailAddresses)
                
            if ($($group.EmailAddressPolicyEnabled))
            {
                Write-Verbose "Turning Back on the Email Address Policy for this distribution group."
                Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$True
            }
        }
    }

    Write-Verbose "New EmailAddresses listed on the original group:"
    (get-distributiongroup $NewName).EmailAddresses | out-string -stream | Where {$_ -ne "" } | ForEach { write-verbose $_ }

}

Some things worth noting

First of all, I’m working trying to make every bit of code I write more of a tool for others rather than something I use in my environment only. As a result, I’m utilizing ShouldContinue and ShouldProcess more. In this script I use them twice. First when I change the Name, Alias and DisplayName fields

    if ( $PSCmdlet.ShouldProcess($OldName, "Setting Name, Alias and DisplayName to $NewName") ) 
	{
		if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Setting Name, Alias and DisplayName to $NewName on target $OldName"  )) )
        {
            Set-DistributionGroup $OldName -alias $NewName -DisplayName $NewName -ForceUpgrade 
        }
    }

The second time I use ShouldProcess and ShouldContinue is when I set the EmailAddresses field.

if ( $PSCmdlet.ShouldProcess($OldName, "Adding new alias to the old address' smtp addresses.") ) 
	{

		if ( -Not $Confirm -or $($PSCmdlet.ShouldContinue("Are you sure you want to make this change?","Adding $NewName addresses on target $OldName"  )) )
        {
            if ($($group.EmailAddressPolicyEnabled))
            {
                Write-Verbose "Turning off the Email Address Policy for this distribution group."
                Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$false
            }
            Write-Verbose "Setting the distribution groups new EmailAddresses setting."
            Set-DistributionGroup $NewName -EmailAddresses $($group.EmailAddresses)
                
            if ($($group.EmailAddressPolicyEnabled))
            {
                Write-Verbose "Turning Back on the Email Address Policy for this distribution group."
                Set-DistributionGroup $NewName -EmailAddressPolicyEnabled:$True
            }
        }
    }

Also, you’ll notice there isn’t much in the way of actual comments. This is a bit of a departure for me as I love my comments. But, rather than use comments, I’ve decided to use Write-Verbose so that everyone can share in “What should be happening.”

Let me know if you have any questions, or if you think there is a better way.

Thanks,
Gene

7 Comments on “Rename a distribution group in Exchange with Powershell”

  1. Hi Gene,

    stupid question, as I am not very familiar with PS:
    How do you run that script / call the function from PS?
    I tried:

    . .\rename_distribution_groups.ps1
    Rename-DistributionGroup -OldName “MyOldGroupName” -NewName “MyNewGroupName”

    I just receive an error “… a parameter with the name “confirm” was defined multiple times…”

    If I add that param, same result:
    Rename-DistributionGroup -OldName “MyOldGroupName” -NewName “MyNewGroupName” -confirm

    Could you pls advise?

    Thx in advance
    BR
    Dan

    1. Hi Dan,
      Looks like you are doing it correctly. try -confirm:$false (if you want it to just run) or -Confirm:$True (if you want it to check with you first).

      1. Gene,

        I’ve tried adding the -confirm parameter the same way you describe, but I still get the same exception: “…A parameter with the name “confirm” was defined muliple times…”

          1. Found solution 🙂

            Replace $Confirm with $MyConfirm everywhere and run 😉

            PS: Probably because of the reserved word in PS

  2. Just to confirm (pun intended?), I am getting the same error. No matter what I do (even trying get-help rename-distributiongroup), I get the “A parameter with the name ‘Confirm’ was defined multiple times for the command’.

  3. This was probably written in the Powershell V2 era. Confirm is now provided by default and could be removed?

    param(
    [Parameter(Mandatory=$true)]
    [string] $OldName,
    [Parameter(Mandatory=$true)]
    [string] $NewName
    )

Leave a Reply