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 |
UserPrincipalName | [email protected] |
Email Address | [email protected] |
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 [email protected]
, thus matching her email address.
We could write a script to update everyone’s UPNs to [email protected]
…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 theADPropertyValueCollection
and expands it into aSystem.Array
object that the rest of PowerShell can work with easily
Output:
smtp:[email protected]
SMTP:[email protected]
smtp:[email protected]
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 margiestravel.com 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="margiestravel.com"}
Comments/questions
There's no commenting functionality here. If you'd like to comment, please either mention me (@[email protected]) on Mastodon or email me. I don't have any logging or analytics running on this website, so if you found something useful or interesting it would mean a lot to hear from you.