How to Update All UPNs in an Organisation to Match Primary Email Address

Written on June 14, 2015

If you’re transitioning to Office 365, Windows Azure Active Directory, or any other of the many ?aaS offerings that require routable UPNs (that is, a UPN with a publicly resolvable domain name that you own) you’ve likely stumbled across a need to change UPNs en masse. While ADUC gives us the option to change just the suffix for everyone in one go, many organisations need to change the left hand name part of this UPN. Consider the following scenario:

User Kim Akers
GivenName Kim
Surname Akers
sAMAccountName KimA
Email Address

This user’s UPN has been generated based on her sAMAccountName, and it doesn’t match her email address. She has no knowledge of what a UPN is, or when it should be used, and it doesn’t make sense to educate on this. In this case, we should update Kim’s UPN to be, thus matching her email address.

We could write a script to update everyone’s UPNs to…or we could be a little more clever. Everyone’s email address is stored in AD, why don’t we just update their UPNs to that?

$user = "KimA"
Get-ADUser $user -Properties proxyAddresses | Select -expand proxyAddresses

How does this work?

  • $user is a string variable storing Kim’s username
  • Get-ADUser retrieves the AD user and some of its properties from AD. Since proxyAddresses isn’t a default parameter returned by Get-ADUser we use the -Properties parameter to have it returned as well
  • Select-Object -expand proxyAddresses takes the ADPropertyValueCollection and expands it into a System.Array object that the rest of PowerShell can work with easily


We can see Kim has three email addresses. How do we translate this to something usable? Let’s try grabbing only Kim’s primary email address*:

Get-ADUser $user -Properties proxyAddresses | Select-Object -Expand proxyAddresses | Where-Object {$_ -clike "SMTP:*"}
  • Where-Object allows us to filter the results
  • -clike performs a case-sensitive like statement, where * is the wildcard character

Great, now let’s clean it up a bit and remove the protocol specifier at the start:

$address = Get-ADUser $user -Properties proxyAddresses | Select -Expand proxyAddresses | Where {$_ -clike "SMTP:*"}
$address = $address.SubString(5)
  • .SubString allows us to select all characters in the string starting at the passed value (5).

Now we can put it all together and update Kim’s UPN:

$User = "KimA"
$address = Get-ADUser $user -Properties proxyAddresses | Select -Expand proxyAddresses | Where {$_ -clike "SMTP:*"}
$address = $address.SubString(5)
Set-ADUser $user -UserPrincipalName $address

Set-ADUser applies the specified update (-UserPrincipalName) to the existing user.

Voila! Kim’s UPN is updated. Now let’s, through the magic of televisionPowerShell, expand this script a little to work for all my users:

# Get all the users who have proxyAddresses under the domain
foreach ($user in (Get-ADUser -SearchBase "DC=MargiesTravel,DC=com" -LdapFilter '(proxyAddresses=*)')) {
	# Grab the primary SMTP address
	$address = Get-ADUser $user -Properties proxyAddresses | Select -Expand proxyAddresses | Where {$_ -clike "SMTP:*"}
	# Remove the protocol specification from the start of the address
	$newUPN = $address.SubString(5)
	# Update the user with their new UPN
	Set-ADUser $user -UserPrincipalName $newUPN

This script requires that all primary email domains are present in AD as UPN suffixes. You can add additional UPN suffixes easily with PowerShell:

Set-ADForest -UPNSuffixes @{Add=""}