Reporting on primary and secondary SMTP addresses on Exchange objects

Most companies have a set of primary Internet domains (Exchange accepted domains) that they use to assign to users. However, a constant is that most companies also assign a secondary email address that has a domain which is identical for all of their users. That is true in my environment, and in that of all customers I have worked with in the past.

However, Exchange tends to generate (especially if you have migrated from legacy Exchange versions) far more email addresses than that for any given Exchange object (user, group, contact).

The script below reports on each user's primary SMTP address, plus a secondary SMTP address whose domain is specified as a parameter.

The script uses the Active Directory PowerShell module, which must be installed on the computer where this script is executed. The script does not use any Exchange specific features, thus the Exchange Management Shell is not required. I tested the script on Exchange 2010 and Exchange 2013, but it should work on Exchange 2007 as well.

A couple of techniques worth noting are used here. First, instead of a function, I use a filter. A filter is a very special kind of a function optimized for working with pipelines of objects. Inputs from the pipeline are passed to the filter using $_.

Second, I parse the proxyAddresses attribute. This attribute contains a list of all addresses that are assigned to a given user. It is an array (a collection) of all those addresses. Importantly, for each item in the collection, the address itself is prefixed by an address type. For SMTP addresses, the address type is "smtp". For FAX addresses, the address type is "fax". For X500 addresses, the address type is "x500". Etc. Also importantly, if the address type is capitalized, then a particular address is the primary address of that type – the default. If the address type is not capitalized, then the address is a secondary address. There may be any number of secondary addresses of a particular type. There may be only one primary address of a particular type.

In order to detect primary addresses, I use the "-ceq" operator in PowerShell. This is "cased equal". That means that the case of the letters is significant. By default, comparisons in PowerShell are not case significant.

Finally, Exchange objects will always have the proxyAddresses attribute populated. This fact is used to build LDAP query utilized to find Exchange objects.

I hope you find this useful!

##
## Get-PrimaryAndSecondary
##
## Michael B. Smith
## April, 2013
##
Param(
	[string]$secondaryDomain = "@TheEssentialExchange.com"
)

[int]$secondaryDomainLen = $secondaryDomain.Length

filter strip-Addresses
{
	$proxies = $_.proxyAddresses

	$primary   = ""
	$secondary = ""

	$object = "" | Select GivenName, Surname, sAMAccountName, PrimarySmtp, SecondarySmtp

	$object.GivenName      = $_.GivenName
	$object.SurName        = $_.SurName
	$object.sAMAccountName = $_.sAMAccountName

	foreach( $proxy in $proxies )
	{
		$len = $proxy.Length

		## note: "SMTP:".Length == 5

		## note: The primary SMTP address has a CAPITALIZED "SMTP:" prefix
		## all secondary SMTP addresses have a lowercase "smtp:" prefix

		## note: any interesting secondary proxy address will be longer than 
		## "SMTP:".Length + $secondaryDomainLen

		if( $len -gt 5 )
		{
			$prefix = $proxy.SubString( 0, 5 )
			$temp   = $proxy.SubString( 5 )	##strip off "smtp:", if present

			if( $prefix -ceq "SMTP:" )
			{
				$primary = $temp
				if( $secondary.Length -gt 0 )
				{
					break   ## we have both primary and secondary, 
						## we don't need to look any more
				}
			}
			elseif( $prefix -ceq "smtp:" -and $len -gt ( 5 + $secondaryDomainLen ) )
			{
				if( $temp.EndsWith( $secondaryDomain ) )
				{
					$secondary = $temp
					if( $primary.Length -gt 0 )
					{
						break   ## we have both primary and secondary, 
							## we don't need to look any more
					}
				}
			}
		}
	}

	$object.PrimarySmtp   = $primary
	$object.SecondarySmtp = $secondary

	$object
}

Import-Module ActiveDirectory

Get-AdUser -LDAPFilter "(&(objectCategory=user)(proxyAddresses=*))" `
	-Properties GivenName, SurName, proxyAddresses -ResultSetSize $null | 
	strip-Addresses

Follow me on twitter, @essentialexch

 

Leave a Reply

Your email address will not be published. Required fields are marked *