Exchange 2003 RUS to Exchange 2010 EAP

Like many of you, I’ve run into the fun situation of moving the Exchange 2003 Recipient Update Services to Exchange 2010’s Email Address Policy.  Although the Exchange Team Blog has a great script (which I highly suggest that you use) for migration, I thought that it might be best to get a list of accounts that *might* be hit with this change.  Pretty much any time that we made a change with RUS, we got bit because of some custom email addresses.

Now at my organization and in my lab, we use First and Last Name with a period separator for the email addresses.  This might be pretty standard, but if yours if different, you may need to alter the script function slightly.  Regardless, here’s the script with some decent comment fields throughout.  Hit me up with any questions!

function ConvertTo-RusAddress
{
    [OutputType([Microsoft.Exchange.Data.SmtpAddress])]
    Param
    (
        [Parameter(Mandatory=$true, 
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true, 
                   Position=0)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [Microsoft.Exchange.Data.Directory.Management.Mailbox]$Mailbox,

        [Parameter(Mandatory=$true, 
                   ValueFromPipeline=$false,
                   ValueFromPipelineByPropertyName=$false, 
                   Position=1)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [string]$EmailDomain
    )

    Begin
    {
        if ( -not ( Get-Command -Name Get-User -ErrorAction SilentlyContinue ) )
        {
            Write-Verbose "Adding Exchange Management PowerShell Snapin"
            Add-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
        }
    }
    Process
    {
        # Build Hash table for extended-ascii conversion
        $ExtendedAscii = @{ 128 = 'C'
                            129 = 'u'
                            130 = 'e'
                            131 = 'a'
                            132 = 'a'
                            133 = 'a'
                            134 = 'a'
                            135 = 'c'
                            136 = 'e'
                            137 = 'e'
                            138 = 'e'
                            139 = 'i'
                            140 = 'i'
                            141 = 'i'
                            142 = 'A'
                            143 = 'A'
                            144 = 'E'
                            145 = 'ae'
                            146 = 'AE'
                            147 = 'o'
                            148 = 'o'
                            149 = 'o'
                            150 = 'u'
                            151 = 'u'
                            152 = 'y'
                            153 = 'O'
                            154 = 'U'
                            160 = 'a'
                            161 = 'i'
                            162 = 'o'
                            163 = 'u'
                            164 = 'n'
                            165 = 'N'
                            225 = 'a'
                            233 = 'e'
                            237 = 'i'
                            243 = 'o'
                            }
        ForEach ( $Item in $Mailbox )
        {
            # Notes:
            #
            # New-Object -TypeName Microsoft.Exchange.Data.SmtpAddress
            # Properties: Local
            #              Domain
            #  Methods:    IsValidAddress
            #              Length

            ##############################################
            # RUS Logic for First.Last@domain.com
            ##############################################
            # 1 - Remove Spaces from First and Last Name
            # 2 - if First is null and Last is null, use the Mailbox Alias
            # 3 - if First is null and Last is not null, use First
            # 4 - if Last is null and First is not null, use Last
            # 5 - if First or Last contain extended-ascii characters, convert them to appropriate ascii characters

            $RusAddress = ""
            $MailboxAlias = $Item.Alias
            $UserInfo = Get-User $Item | Select-Object FirstName, LastName
            $FirstName = $UserInfo.FirstName
            $LastName  = $UserInfo.LastName
            Remove-Variable $UserInfo -ErrorAction SilentlyContinue
            # Check for first and last nulls
            if ( $FirstName ) # exists, ie. is not $null
            {
                # Remove Spaces from the First Name
                $FirstName = $FirstName.Replace(' ', '')
                # Remove apostrophes from the First Name
                $FirstName = $FirstName.Replace("'", "")
            }
            if ( $LastName ) # exists, ie. is not $null
            {
                # Remove Spaces from the Last Name
                $LastName  = $LastName.Replace(' ', '')
                # Remove apostrophes from the Last Name
                $LastName = $LastName.Replace("'", "")
            }
            if ( $FirstName -and $LastName )
            { # Both first and last name exist
                $RusAddress = $FirstName + "." + $LastName + "@" + $EmailDomain
            }
            elseif ( $FirstName -and -not $LastName )
            { # First Name exists, but Last does not
                $RusAddress = $FirstName + "@" + $EmailDomain
            }
            elseif ( -not $FirstName -and $LastName )
            { # Last Name exists, but first does not
                $RusAddress = $LastName + "@" + $EmailDomain
            }
            elseif ( -not $FirstName -and -not $LastName )
            { # neither first or last exist
                $RusAddress = $MailboxAlias + "@" + $EmailDomain
            }
            else
            { # no clue how it could reach here
                Write-Error "Function Failure"
                break
            }

            # Lastly, strip out any extended ASCII Characters
            $ReturnString = ""
            For ( $i = 0; $i -lt $RusAddress.Length; $i++ )
            {
                $CharCode = [int][char]$RusAddress[$i]
                if ( $ExtendedAscii[$CharCode] )
                {
                    $ReturnString += $ExtendedAscii[$CharCode]
                }
                else
                {
                    $ReturnString += $RusAddress[$i]
                }
            }

            return $ReturnString

        }

    }
    End
    {
    }
}

if ( -not ( Get-Command -Name Get-Mailbox -ErrorAction SilentlyContinue ) ) 
{
    Write-Verbose "Adding Microsoft Exchange 2010 PowerShell Snapin"
    Add-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
}

Write-Host "Getting all mailboxes: " -NoNewline
$Mailboxes = Get-MailboxDatabase | Get-Mailbox -ResultSize Unlimited | Sort-Object DisplayName
Write-Host "$( $Mailboxes.Count ) mailboxes found."
# RUS Logic for First.Last@domain.com
##############################################
# 1 - Remove Spaces from First and Last Name
# 2 - if First is null and Last is null, use the Mailbox Alias
# 3 - if First is null and Last is not null, use First
# 4 - if Last is null and First is not null, use Last
# 5 - if First or Last contain extended-ascii characters, convert them to appropriate ascii characters

Write-Host "Extending Mailbox Object with Calculated RUS Email Address"
$Mailboxes | Add-Member -MemberType ScriptProperty -Name RusEmailAddress -Value { $this | ConvertTo-RusAddress -EmailDomain "domain.com" } -Force
Write-Host "Extending Mailbox Object with RUS <-> Primary Address Comparison"
$Mailboxes | Add-Member -MemberType ScriptProperty -Name RusMatches -Value { $this.RusEmailAddress -eq $this.PrimarySmtpAddress.ToString() } -Force

# Dump Everything to a CSV File (for record keeping)
Write-Host "Export selected fields to CSV"
$Mailboxes | Sort-Object DisplayName | Select-Object DisplayName, HiddenFromAddressListsEnabled, PrimarySMTPAddress, RusEmailAddress, RusMatches, EmailAddressPolicyEnabled | Export-Csv -Path "C:inetpubwwwrootRusMailboxes.csv" -NoTypeInformation -Force -Encoding ASCII
Write-Host "Export selected fields to HTML"
$Mailboxes | Sort-Object DisplayName | Select-Object DisplayName, HiddenFromAddressListsEnabled, PrimarySMTPAddress, RusEmailAddress, RusMatches, EmailAddressPolicyEnabled | ConvertTo-Html -Title "RUS Check" | Out-File -FilePath "C:inetpubwwwrootRusMailboxes.htm" -Force -Encoding ASCII

#Possible Outcomes:
# Rus Email Address matches Primary SMTP
#  Email Address Policy is enabled       - Best Solution - the "general" way things should work
#  Email Address Policy is disabled      - Doesn't matter, but maybe we should turn on the Email Adddress Policy
#
# Rus Email DOES NOT match Primary SMTP
#  Email Address Policy is enabled       - BAD - need to disable Email Address Policy
#  Email Address Policy is disabled      - Correct configuration for non-standard users
#

# (OPTIONAL)
# Flip off Email Address Policy for accounts where there is a mismatch between the RUS and the EAP email.
$MismatchedRus = $Mailboxes | Where-Object { -not $_.RusMatches -and $_.EmailAddressPolicyEnabled }

ForEach ( $Mailbox in $MismatchedRus )
{
    $Mailbox | Set-Mailbox -EmailAddressPolicyEnabled:$false -WhatIf
}

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.