Converting SMTP Proxy Addresses to Lowercase
Update: Be aware, this script has not been tested with SIP, X400 or other address types. I am working on an update to validate these scenarios, but in the meantime, proceed at your own risk with these address types.
I recently encountered a question in an online forum where someone asked for a script to convert all of their user’s email addresses to lower case values. While this doesn’t affect the message delivery, it can have an impact on aesthetics when the address is displayed in an external recipient’s email client. An Exchange Email Address Policy can do this to some degree, but I wanted to see how it could be done with PowerShell.
The challenge with a script like this is twofold:
- Email addresses (proxy addresses) are a multi-valued attribute, which can be tricky to work with.
- PowerShell is generally not case-sensitive, and therefore when we try to rename Mr. Gallalee’s email address in the screenshot below, we can see that it does not work:
After a little bit of inspiration from a script written by Michael B Smith, I came up with the below:
$MailboxList = Get-Mailbox -ResultSize unlimited
$MailboxList | % {
$LoweredList = @()
$RenamedList = @()
foreach ($Address in $_.EmailAddresses){
if ($Address.prefixstring -eq "SMTP"){
$RenamedList += $Address.smtpaddress + "TempRename"
$LoweredList += $Address.smtpaddress.ToLower()
}
}
Set-mailbox $_ -emailaddresses $RenamedList -EmailAddressPolicyEnabled $false
Set-mailbox $_ -emailaddresses $LoweredList
#Without this line the "Reply To" Address could be lost on recipients with more than one proxy address:
Set-mailbox $_ -PrimarySmtpAddress $_.PrimarySmtpAddress
}
This script works as follows:
- Puts all mailboxes into the $MailboxList variable. If you don’t want all mailboxes, edit the Get-Mailbox cmdlet as you see fit.
- Filters out X400 and other non-SMTP addresses.
- Creates an array called $RenamedList which stores each proxy address with “TempRename” appended to it (e.g. Rgallalee@demolab.localTempRename).
- Creates another array ($LoweredList) and use the “ToLower” method on each proxy address.
- Sets the proxy address for the user to the value of $RenamedList and then to $LoweredList.
- This is how we get around the case case insensitivity – name it to something else and then name it back.
- Step 4 and 5 don’t preserve the “Primary” / “Reply-To” address, so we set it back manually with the last line.
Note: This script turns off the email address policy for each user.
As always, feedback is welcome.
100,000 and Counting…
I am proud to report that today this blog has reached 100,000 views! Maintaining this site has been very rewarding for me, and I’m happy to have been able to contribute to the technical community, which has served me very well since I entered the infotech industry ten years ago.
WordPress.com provides statistics on how every blog is used. Here are some facts about mine:
- My post on setting logon wallpaper for Windows 7 has been my most popular
- Google’s search results have sent most of my readers (by far). TechNet forums comes in 2nd
- Google has sent people to this site at a rate 34x to that of Bing
- Only 9 viewers have used ask.com to find me (GASP!)
- The anti-spam feature for comments is very good, though the comment spam I receive has been surprisingly complementary; I’m half way inclined to let it through.
Thanks to all my visitors. Please share my site with a friend, visit the sites that pay my bills (Mike’s Links – top right), and if you have any topic suggestions or feedback in general, please contact me!
Combining PowerShell Cmdlet Results
In my last post I used used New-Object to create an desirable output when the “Get-Mailbox” cmdlet didn’t meet my needs. If your eyes glazed over trying to read the script, let me make it a bit simpler by focusing on a straight forward example.
Say you need to create a list of user’s mailbox size with their email address. This sounds like a simple request, but what you’d soon find is that mailbox sizes are returned with the Get-MailboxStatistics cmdlet and the email address is not. For that, you need to use another cmdlet, such as Get-Mailbox.
With the New-Object cmdlet, we are able to make a custom output that contains data from essentially wherever we want.
See this example:
$MyObject = New-Object PSObject -Property @{
EmailAddress = $null
MailboxSize = $null
}
In this example, I have created a new object with 2 fields, and saved it as the $MyObject variable.
For now, we’ve set the data to null, as shown below:
The next step is to populate each of those fields. We can write to them one at a time with lines like this:
$MyObject.EmailAddress = (Get-Mailbox mcrowley).PrimarySmtpAddress $MyObject.MailboxSize = (Get-MailboxStatistics mcrowley).TotalItemSize
Note: The variable we want to populate is on the left, with what we want to put in it on the right.
To confirm our results, we can simply type the variable name at the prompt:
Pretty cool, huh?
Ok, so now about that list. My example only shows the data for mcrowley, and you probably need more than just 1 item in your report, right?
For this, you need to use the foreach loop. You can read more about foreach here, but the actual code for our list is as follows:
(I am actually going to skip the $null attribute step here)
$UserList = Get-mailbox -Resultsize unlimited
$MasterList = @()
foreach ($User in $UserList) {
$MyObject = New-Object PSObject -Property @{
EmailAddress = (Get-Mailbox $User).PrimarySmtpAddress
MailboxSize = (Get-MailboxStatistics $User).TotalItemSize
}
$MasterList += $MyObject
}
$MasterList
Finally, if you wanted to make this run faster, we really don’t need to run “get-mailbox” twice. For better results, replace the line:
EmailAddress = (Get-Mailbox $User).PrimarySmtpAddress
With this one:
EmailAddress = $User.PrimarySmtpAddress
Exchange Proxy Address (alias) Report
###
UPDATE (June 1 2012): This script now runs faster and puts the “Primary” SMTP address first. For example:
###
Exchange Server stores user’s alternate email addresses as a multi-valued attribute within Active Directory. For example, if my colleague Jorge has jdiaz@demolab.local as well as diazj@demolab.local, his proxyAddresses attribute would look like this:
Notice, the capital SMTP vs. the lowercase smtp. There can be only one uppercase SMTP, and this represents the primary, or “reply to” address.
While, it’s very easy to view someone’s proxy addresses (often called aliases, but don’t confuse it with the “alias” attribute) within the Exchange Management Console, it can be tough to work with in the Exchange Management Shell (PowerShell) due to the data being stored as a “Multi-Valued” attribute. The usual “Get-Mailbox” output not only shows all addresses as a single item, but in the case “mcrowley” below, we can see the shell truncates:
While there are ways (example1, example2) to manipulate this output on the screen, I recently needed to create a complete list of all users possessing one or more secondary email address, and document what those addresses were.
On the surface, this sounds simple. We want a list of users who have more than 1 proxy address. At first, I thought of something like this:
Get-Mailbox -Filter {emailaddresses -gt 1} | Select EmailAddresses
But we can see this doesn’t actually capture the correct users. In the above example, LiveUser1 only has a single proxy address, but it was returned anyway. This is because the result is actually converted to a number, and the “-gt” or “greater than” operation is done on this number; not what we want.
To get the user collection you want, we actually need to break-out the data within this attribute, and evaluate it in a somewhat CPU intensive process. I have written a script that helps here, by doing the following things:
- Grabs all mailboxes and counts the number of proxy addresses for each one. I have filtered out X400, and other non-smtp addresses.
- If more than one proxy is found, it puts the user and it’s proxy addresses in a “nice” CSV file called c:\TooManyProxies.csv.
- Displays a similar output to the screen.
- Displays the total number of users found.
Here is a sample output, shown in excel (with some bolding on the headers):
The guts of this script might help with this exact scenario, or really, anywhere you want to break out and evaluate multi-valued attributes. Feel free to use it and adjust as you see fit!
Some known limitations:
- I’m no PowerShell master, so this might not be as efficient as it could be.
- If a user has more than 10 proxy addresses, you’ll need to adjust the script and add more rows.
- There isn’t a lot of error checking here, but I’ve used it in 2 different environments and it ran as expected.
As shown below, this script doesn’t differentiate “SMTP” from “smtp”. The addresses are listed in order stored; not necessarily relevant to us. If you want this information shown, remove this portion from the script:
If you ONLY want a csv of everyone’s proxy address, change “-gt 1″ to “-gt 0″
Finally, the script itself:
#ProxyAddressCount-v3.3
# by Mike Crowley http://mikecrowley.us
cls
Write-Host "Getting and evaluating users. Please wait; this could take a while..." -ForegroundColor Cyan
#Getting a list of mailboxes to work with
$UserList = Get-mailbox -Resultsize unlimited
$TooManyProxies = @()
foreach ($User in $UserList) {
#get a list of SMTP and smtp proxy addresses for each User
[array]$SmtpProxyAddresses = $User.emailaddresses | Where {$_.prefixstring -like 'smtp'} | sort IsPrimaryAddress -Descending
#This section creates a lot of errors since many users don't have 3,4,5 etc proxy addresses. Here we turn error output off.
$ErrorActionPreference = 'SilentlyContinue'
#Create a new placeholder object so that we don't store the x400/x500 proxy addresses
$UserAndSmtpObject = New-Object PSObject -Property @{
Name = $user.name
PrimarySmtpAddresses1 =$SmtpProxyAddresses[0] -replace "smtp:"
SmtpAddresses2 =$SmtpProxyAddresses[1] -replace "smtp:"
SmtpAddresses3 =$SmtpProxyAddresses[2] -replace "smtp:"
SmtpAddresses4 =$SmtpProxyAddresses[3] -replace "smtp:"
SmtpAddresses5 =$SmtpProxyAddresses[4] -replace "smtp:"
SmtpAddresses6 =$SmtpProxyAddresses[5] -replace "smtp:"
SmtpAddresses7 =$SmtpProxyAddresses[6] -replace "smtp:"
SmtpAddresses8 =$SmtpProxyAddresses[7] -replace "smtp:"
SmtpAddresses9 =$SmtpProxyAddresses[8] -replace "smtp:"
SmtpAddresses10 =$SmtpProxyAddresses[9] -replace "smtp:"
}
#Turning error reporting back on
$ErrorActionPreference = 'Continue'
#Count the number of proxy addresses for each User
$SmtpProxyAddressCount = ($SmtpProxyAddresses).count
#Add Users with more than 1 proxy address to the $TooManyProxies variable
if ($SmtpProxyAddressCount -gt 1) {
$TooManyProxies += $UserAndSmtpObject
}
}
Write-Host ""
$TooManyProxies | select name, PrimarySmtpAddresses1, SmtpAddresses2, SmtpAddresses3, SmtpAddresses4, SmtpAddresses5, SmtpAddresses6, SmtpAddresses7, SmtpAddresses8, SmtpAddresses9, SmtpAddresses10 | Export-CSV c:\TooManyProxies.csv -notype
$TooManyProxies | select name, PrimarySmtpAddresses1, SmtpAddresses2, SmtpAddresses3, SmtpAddresses4, SmtpAddresses5, SmtpAddresses6, SmtpAddresses7, SmtpAddresses8, SmtpAddresses9, SmtpAddresses10
Write-Host ""
#Display a count
Write-Host "You had" ($TooManyProxies).count "Users containing two or more proxy SMTP addresses." -ForegroundColor Cyan
Write-Host ""
Write-Host ""
Write-Host "Your result file is here 'c:\TooManyProxies.csv'" -ForegroundColor Cyan
Cloud Connections Session Slides
Thanks to those who attended my sessions at this weeks Cloud Connections conference. If you missed it, or would like to download the slides, I’ve made them available here.
If you are looking for slides from other speakers, please see here:
http://www.devconnections.com/updates/LasVegas_Spring12/Cloud
Ads are Annoying
Thanks to all who read my blog! Today I purchased the “No Ads” upgrade, and thus made the internet a cleaner place. Hope you all enjoy.


Windows Server “8” Beta Hyper-V Component Architecture Poster
Late last week, Microsoft released another high-quality poster. This time for Hyper-V in Windows 8 (beta).
You can download this poster here.
If you’re interested in learning more on Hyper-V in Windows 8, click some of the links below. This update to Hyper-V is my favorite part of Windows Server 8!
Reading
- Understand and Troubleshoot Hyper-V Replica in Windows Server "8" Beta
- How does Storage Migration actually work?
Videos




