Office 365 PowerShell Tip – Keeping EmailAddress and UPN in Sync

UPN’s are a nice way for our users to remember their usernames.  A UPN essentially has the same format as an email address.  Rather than having users login to their workstations or intranet resources as CLOUD\Username, they can login as user.lastname@cloud.com which can be the same as their email address.

Problem
When moving to Office 365 and are using DirSync with or without ADFS, your users need to have a UPN with a public routable domain in it. The easiest and most logical way to do that for your users sake is to keep UPN and primary email address the same.

Solution(s)
There are of course a lot of different solutions out there for achieveing the above, many of them include PowerShell and csv-files. My solution is based on PowerShell and are utilizing either Exchange Powershell cmdlets or Active Directory cmdlets.

Solution 1 (Exchange 2007 and above)
The below example is a very quick one that you run in Exchange Management Shell in Exchange 2007 and above. It simply copies the “WindowsPrimaryEmailAddress” for all your user mailboxes to the userPrincipalName attribute, without any question.

Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox | ForEach { Set-Mailbox -Identity $_.Guid.ToString() -UserPrincipalName $_.WindowsEmailAddress.ToString() } 

To verify that the change has been properly done, you can run the below command to list all mailboxes that have different primary email address and UPN:

Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox | Where-Object {$_.UserPrincipalName -ne $_.WindowsEmailAddress.ToString() }

Solution 2 (Exchange 2003 and above)
I had a case where the customer was running Exchange 2003, but had 2008R2 domain controllers. The customer also wanted a log file with the old and the new UPN after the change had been done. The script utilizes the ActiveDirectory module for PowerShell and copies the primary email address from the proxyAddresses attribute.
Running the script without any switches makes it run in test mode and do the AD-changes with the -WhatIf, so no changes will be done here.

2014-01-01 16-09-06

Running the script with the switch -Production makes it do the actual changes.2014-01-01 16-09-22

For backup purposes, the script are also creating a log file with the old and new attribute in the same folder where you run the script.

<#  
.SYNOPSIS 
    Script that copies the primary emailaddress from proxyAddresses to the userPrincipalName attribute.  
    It runs in test mode and just logs the changes that would have bee done without any parameters.  
    It identifies an exchange user with the legacyExchangeDN-attribute.  
.PARAMETER Production 
    Runs the script in production mode and makes the actual changes. 
.NOTES 
    Author: Johan Dahlbom 
    Blog: 365lab.net 
    Email: johan[at]dahlbom.eu 
    The script are provided “AS IS” with no guarantees, no warranties, and they confer no rights.     
#>
param(
[parameter(Mandatory=$false)]
[switch]
$Production = $false
)
#Define variables
$PSScriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
$DateStamp = Get-Date -Format "yyyy-MM-dd-HH-mm-ss"
$Logfile = $LogFile = ($PSScriptRoot + "\ProxyUPNSync-" + $DateStamp + ".log")
Function LogWrite
{
Param ([string]$logstring)
Add-content $Logfile -value $logstring
Write-Host $logstring
}
    try
    {
        Import-Module ActiveDirectory -ErrorAction Stop
    }
    catch
    {
        throw "Module ActiveDirectory not Installed"
    }

#For each AD-user with a legacyExchangeDN, look up primary SMTP: in proxyAddresses
#and use that as the UPN
$CollObjects=Get-ADObject -LDAPFilter "(&(legacyExchangeDN=*)(objectClass=user))" -Properties ProxyAddresses,distinguishedName,userPrincipalName

            foreach ($object in $CollObjects)
            {
                $Addresses = $object.proxyAddresses
                $DN=$object.distinguishedName
                    foreach ($Address In $Addresses)
                    {
                        $ProxyArray=($ProxyArray + "," + $Address)
                        If ($Address -cmatch "SMTP:")
                            {
                                $PrimarySMTP = $Address
                                $UserPrincipalName=$Address -replace ("SMTP:","")
                                    #Found the object validating UserPrincipalName
                                    If ($object.userPrincipalName -notmatch $UserPrincipalName) {
                                        #Run in production mode if the production switch has been used
                                        If ($Production) {
                                            LogWrite ($DN + ";" + $object.userPrincipalName + ";NEW:" + $UserPrincipalName)
                                            Set-ADObject -Identity $DN -Replace @{userPrincipalName = $UserPrincipalName}
                                        }
                                        #Runs in test mode if the production switch has not been used
                                        else {
                                            LogWrite ($DN + ";" + $object.userPrincipalName + ";NEW:" + $UserPrincipalName)
                                            Set-ADObject -Identity $DN -WhatIf -Replace @{userPrincipalName = $UserPrincipalName}
                                        }
                            }
                            else
                            {
                            Write-Host "Info: User $($object.UserPrincipalName) are already OK!"

                            }
                        }
                    }
            }

Hope the above was helpful to you, please let me know if you have any questions!

/Johan

Advertisements

2 thoughts on “Office 365 PowerShell Tip – Keeping EmailAddress and UPN in Sync

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s