0 votes

We're looking at adding a powershell script to check for duplicate Exchange Aliases within our exchange organization prior to a user modification. We've noticed that Exchange 2010 will allow duplicate Exchange Aliases to exist (to be created) and we'd like to block that feature by simply adding a number to the end of the new alias.

A script similar to the following would be ideal:

Import-Module Adaxes
function IsUserNameUnique($username)
{
   $user = Get-AdmUser $username -erroraction silentlycontinue
   return $user -eq $Null;
}
# Get the username
$username = $Context.GetModifiedPropertyValue("samAccountName");
# Check if the username is unique
if (IsUserNameUnique($username))
{
    return;
}
# If the username is not unique, generate a unique one
$uniqueUsername = $Null;
for ($i = 1; $True; $i++)
{
    $uniqueUsername = $username + $i;
    if (IsUserNameUnique($uniqueUsername))
    {
        break;
    }
}
# Update User Logon Name (pre-Windows 2000)
$Context.SetModifiedPropertyValue("samAccountName", $uniqueUsername);
# Update User Logon Name
$Context.SetModifiedPropertyValue("userPrincipalName", "$uniqueUsername@domain.com");
$Context.LogMessage("Username: " + $username + " already exists!", "Warning");
$Context.LogMessage("The user's logon name has automatically been changed to:", "Error");
$Context.LogMessage($uniqueUsername, "Error");
$Context.LogMessage("The user's email address will now be:", "Error")
$Context.LogMessage($uniqueUsername + "@domain.com", "Error");

Thanks for your assistance!

by (610 points)

1 Answer

0 votes
by (216k points)

Hello,

Here you are. The following script creates an alias that will be unique across all domains managed by Adaxes:

# Get the exchange alias
$exchangeAlias = $Context.Action.MailAlias

function IsExchangeAliasUnique($exchangeAlias)
{
    # Search all aliases
    $searcher = New-Object "Softerra.Adaxes.Adsi.Search.DirectorySearcher" $NULL, $False
    $searcher.SearchParameters.PageSize = 500
    $searcher.SearchParameters.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.SearchParameters.Filter = "(&(objectCategory=user)(mailNickname=$exchangeAlias))"
    $searcher.VirtualRoot = $True

    $result = $searcher.ExecuteSearch()
    $users = $result.FetchAll()
    $result.Dispose()

    if($users.Count -eq 0)
    {
        return $True
    }

    return $False
}

# Check if the exchange alias is unique
if (IsExchangeAliasUnique($exchangeAlias))
{
    return
}

# If the exchange alias is not unique, generate a unique one
$uniqueExchangeAlias = $Null;
for($i = 1; $True; $i++)
{
    $uniqueExchangeAlias = $exchangeAlias + $i
    if(IsExchangeAliasUnique($uniqueExchangeAlias))
    {
        $Context.Action.MailAlias = $uniqueExchangeAlias
        break
    }
}

$Context.LogMessage("New exchange alias: $uniqueExchangeAlias", "Information") # TODO: modify me
0

This is great, thank you!

Is there a way to limit the search to a particular AD domain? Below is my attempt at modifying this query and while the script does not error, it never actually completes so I've introduced some sort of loop...

# Get the exchange alias
$exchangeAlias = $Context.Action.MailAlias

function IsExchangeAliasUnique($exchangeAlias)
{
    # Search all aliases

    $admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
    $admService = $admNS.GetServiceDirectly("localhost")
    $searcher = $admService.OpenObject("Adaxes://DC=CORP,DC=DOMAIN,DC=INT", $NULL, $NULL, 0)
    $searcher.SearchParameters.PageSize = 500
    $searcher.SearchParameters.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.SearchParameters.Filter = "(&(objectCategory=user)(mailNickname=$exchangeAlias))"

    $result = $searcher.ExecuteSearch()
    $users = $result.FetchAll()
    $result.Dispose()

    if($users.Count -eq 0)
    {
        return $True
    }

    return $False
}

# Check if the exchange alias is unique
if (IsExchangeAliasUnique($exchangeAlias))
{
    return
}

# If the exchange alias is not unique, generate a unique one
$uniqueExchangeAlias = $Null;
for($i = 1; $True; $i++)
{
    $uniqueExchangeAlias = $exchangeAlias + $i
    if(IsExchangeAliasUnique($uniqueExchangeAlias))
    {
        $Context.Action.MailAlias = $uniqueExchangeAlias
        break
    }
}

$Context.LogMessage("New exchange alias: $uniqueExchangeAlias", "Information") # TODO: modify me
0

Hello,

Here you are. This version of the script checks whether the alias is unique only within the domain of the target object.

# Get the exchange alias
$exchangeAlias = $Context.Action.MailAlias

function IsExchangeAliasUnique($exchangeAlias)
{
    $domainName = $Context.GetObjectDomain("%distinguishedName%")

    # Search all aliases
    $searcher = $Context.BindToObject("Adaxes://$domainName/rootDSE")
    $searcher.PageSize = 500
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.SearchFilter = "(&(sAMAccountType=805306368)(mailNickname=$exchangeAlias))"
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"

    $result = $searcher.ExecuteSearch()
    $users = $result.FetchAll()
    $result.Dispose()

    if($users.Count -eq 0)
    {
        return $True
    }

    return $False
}

# Check if the exchange alias is unique
if (IsExchangeAliasUnique($exchangeAlias))
{
    return
}

# If the exchange alias is not unique, generate a unique one
$uniqueExchangeAlias = $Null;
for($i = 1; $True; $i++)
{
    $uniqueExchangeAlias = $exchangeAlias + $i
    if(IsExchangeAliasUnique($uniqueExchangeAlias))
    {
        $Context.Action.MailAlias = $uniqueExchangeAlias
        break
    }
}

$Context.LogMessage("New exchange alias: $uniqueExchangeAlias", "Information") # TODO: modify me
0

Thanks for the response!

Unfortunately, the error I'm getting now is this (after adding an additional context.logmessage at the end to clarify the email address):

Exception calling "FetchAll" with "0" argument(s): "The search filter cannot be recognized. (Server: corp.domain.int)"
Property 'MailAlias' cannot be found on this object; make sure it exists and is settable.
Exchange alias exists, auto-generated new exchange alias is: 1
New Primary Exchange SMTP address will be: 1@domain.org

I'm using a business rule that runs before updating a user...

0

Hello,

That version of the script was for a Business Rule triggered before establishing an e-mail address.

If you are using a Business Rule triggered before updating a user, you need to use the following script:

# Get the Exchange Alias
$exchangeAlias = $Context.GetModifiedPropertyValue("mailNickname")

function IsExchangeAliasUnique($exchangeAlias)
{
    $domainName = $Context.GetObjectDomain("%distinguishedName%")

    # Search all aliases
    $searcher = $Context.BindToObject("Adaxes://$domainName/rootDSE")
    $searcher.PageSize = 500
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.SearchFilter = "(&(sAMAccountType=805306368)(mailNickname=$exchangeAlias))"
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"

    $result = $searcher.ExecuteSearch()
    $users = $result.FetchAll()
    $result.Dispose()

    if($users.Count -eq 0)
    {
        return $True
    }

    return $False
}

# Check if the Exchange Alias is unique
if (IsExchangeAliasUnique($exchangeAlias))
{
    return
}

# If the exchange alias is not unique, generate a unique one
$uniqueExchangeAlias = $Null;
for($i = 1; $True; $i++)
{
    $uniqueExchangeAlias = $exchangeAlias + $i
    if(IsExchangeAliasUnique($uniqueExchangeAlias))
    {
        $Context.SetModifiedPropertyValue("mailNickname", $uniqueExchangeAlias) 
        break
    }
}

$Context.LogMessage("New exchange alias: $uniqueExchangeAlias", "Information") # TODO: modify me
0

This script works fantastically, thank you!

One issue we have found recently is that occasionally a modification to an account's FirstName does not result in a change in the Alias due to the way we construct our aliases. For example, the alias for Joe Smith would be SmithJ in our company. If the change being made was for the first name as in "Joseph" instead of "Joe" then the alias would remain "SmithJ".

We've found that the script to check for Exchange Alias uniqueness executes in this scenario, locates the account's own "SmithJ" alias, identifies it as a duplicate and creates a new one for "SmithJ2".

I have been attempting to add in an IF statement to first evaluate if there is a difference between the modified "mailNickname" and the existing %mailNickname% before running the isExchangeAliasUnique function. The following code does not work properly as the two variables are always the same...

If ($exchangeAlias -ne "%mailNickname%")

Any help would be appreciated, thank you!

<EDITED for clarity>

0

Hello,

We've asked our script guys to have a look. We'll update this topic as soon as they come up with something.

0

Thank you!

0

Hello,

Actually, the only thing you need to do is to change the filter that's used for finding users with the same Exchange Alias. To do this:

  1. Find the following line in the script:

         $searcher.SearchFilter = "(&(sAMAccountType=805306368)(mailNickname=$exchangeAlias))"
  2. Replace it with the following:

         $searcher.SearchFilter = "(&(sAMAccountType=805306368)(mailNickname=$exchangeAlias)(!(distinguishedName=%distinguishedName%)))"

Now, the search will return users who have the same Exchange Alias, but not the same Distinguished Name (DN).

Related questions

0 votes
1 answer

This will run in a business rule "after creating a user" The email should be set to %firstname:lower%%lastname:lower%@mydomain. If the email isn't unique then it ... failure. This should update the emailaddress attribute in AD(not updating anything in Azure).

asked Feb 2, 2023 by mightycabal (1.0k points)
0 votes
0 answers

Hi, relatively new to Adaxes. We use a third party for our mail archiving solution for this to work account we have for this 3rd party needs full access to every mailbox. On ... I get stuck at the rest. Would anyone be able to assist? Thanks in advance Gary

asked Apr 29, 2020 by caoky (20 points)
0 votes
1 answer

Hi, relatively new to Adaxes. We use a third party for our mail archiving solution for this to work account we have for this 3rd party needs full access to every mailbox. On ... I get stuck at the rest. Would anyone be able to assist? Thanks in advance Gary

asked Dec 12, 2017 by gazoco (490 points)
0 votes
1 answer

Is there a way to make this script (Test-ExchangeServerHealth.ps1) work as a scheduled task or a Custom Command that dispays or emails the output to a specified email address? http://exchangeserverpro.com/powershell ... hange-2010\

asked Dec 12, 2012 by mdeflice (350 points)
0 votes
1 answer

I am using this script modified for my testing. Import-Module Adaxes $csvFilePath = "D:\TestFeed\ImportNewUsers.csv" # Path to pick up feed file $userIdColumn = "Employee Number" # TODO: ... initial. I would like to add a 2 for now if the sam isn't unique.

asked Oct 17, 2022 by mightycabal (1.0k points)
3,326 questions
3,026 answers
7,727 comments
544,678 users