Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Powershell way to quickly search email addresses (all types)

2,774 views
Skip to first unread message

Tim Cross

unread,
Dec 6, 2008, 9:32:00 AM12/6/08
to
I have a powershell script to create certain 'default' proxy addresses our
company has gotten used to, such as X400 with First and Last, X400 with our
logon ID, X500 with logon ID, smtp aliases for logon ID's and
First...@domain.com. Using any script it is too easy to try to add a
duplicated proxy address. What I would like is a way to have my powershell
script build an address then do a quick search to see if it already exists.
If it exists do NOT add it to a user's emailaddresses property. If it des
NOT exist then ADD it to a user's emailaddresses property. I can do all but
a quick search first to see if the email proxy address I am trying to build
already exists.

Andy David {MVP}

unread,
Dec 6, 2008, 9:40:47 AM12/6/08
to


Why do you create x500 addresses?

Tim Cross

unread,
Dec 6, 2008, 9:51:01 AM12/6/08
to
Primarily (but not limited to this) to duplicate moved mailboxes'
LegacyExchangeDN property as an X500 proxy so we can later fix the
LegacyExchangeDN field up and thus be able to remove a no longer needed
Administrative Group (or Site from Exchange 5.5 days). We want to move all
of our Exchange 2003 mailboxes to Exchange 2007 and being able to manipulate
certain proxy addresses (like x500) will allow us to fix up accounts to later
be able to remove 'emptied' Administrative Groups.

Rich Matheisen [MVP]

unread,
Dec 6, 2008, 11:34:07 AM12/6/08
to
On Sat, 6 Dec 2008 06:32:00 -0800, Tim Cross
<TimC...@discussions.microsoft.com> wrote:

See if this works (ignore the line wrap -- each command is on its own
line):


$searcher = new-object DirectoryServices.DirectorySearcher

$users = import-csv . . . .

:TRYANOTHER
foreach ($user in $users)
{
$addr = $user.'emailaddress'
filer = "(proxyaddresses=$addr)"

searcher.filter = $filter

result = $null
result = $searcher.FindOne
if ($result -ne $null)
{
$dn = $result.properties.distinguishedname
write-host "Address '$addr' used by at least one other
user:`n`t$dn"
continue "TRYANOTHER"
}
}
---
Rich Matheisen
MCSE+I, Exchange MVP

Tim Cross

unread,
Dec 6, 2008, 12:37:01 PM12/6/08
to
Possibly. How about a brief synopsis (maybe pseudo code like) of what I am
doing:
$mailboxes = get-mailbox -ignoredefaultscope:$true -resultsize unlimited
-sort alias
Above line gets all my mailboxes (parent and child domains), almost 2000
mailboxes.

if ($ukxchservers.contains($mbx.servername))
{$thisdc = "londom01.europe.wwwint.corp"}
else
{$thisdc = "rocdom01.wwwint.corp"}
$SourceRecipient = Get-Mailbox $thisuser -domaincontroller $thisdc
$SourceUser = Get-User $thisuser -domaincontroller $thisdc
Above steps allow me to chose the DC to get user info.

$OldLegacyExchangeDN = $SourceRecipient.LegacyExchangeDN
if ($sourcerecipient.serverlegacydn.contains("OU="))
{$homemta =
$sourcerecipient.serverlegacydn.substring($sourcerecipient.serverlegacydn.indexof("OU=")+3)}
else
{$homemta =
$sourcerecipient.serverlegacydn.substring($sourcerecipient.serverlegacydn.indexof("ou=")+3)}
$homemta = $homemta.substring(0,$homemta.indexof("/"))
$EmailAddresses = $SourceRecipient.EmailAddresses
$logonid = $SourceRecipient.SamAccountName
$firstname = $SourceUser.FirstName
$lastname = $SourceUser.LastName
Above lets me get some vars set for things to do for this user.

if ($EmailAddresses.contains("X500:" + $x500addrID) -or
$EmailAddresses.contains("x500:" + $x500addrID)) {$toaddx500ID = "False"}
This lets me check for the existence of the X500 or x500 version of the
built address for this user.

if ($addr.proxyaddressstring.contains("X500:")) {$addx500 = "True"}
This lets me determine if any primary X500 exists for this user.

if ($toaddx500ID -eq "True")
{
$changed = "True"
if ($addx500 -eq "True")
{$EmailAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]("x500:"
+ $x500addrID)}
else
{$EmailAddresses += [Microsoft.Exchange.Data.CustomProxyAddress]("X500:"
+ $x500addrID)}
}
Here I get ready to add the new address. Before I actually do this is where
I would want to search ALL of my organization's proxy addresses to see if
there may already be a match so I don't give the same address to two
different mailboxes.
Looping through almost 2000 mailboxes, the search needs to be quick or the
above steps could take way to long to be usable.
Make any more sense what it is I am trying to do? Even though I look mostly
at X500 in above steps my actual routine is processing all X400, X500, as
well as all SMTP addresses of all of my mailboxes.

Rich Matheisen [MVP]

unread,
Dec 6, 2008, 3:34:40 PM12/6/08
to
On Sat, 6 Dec 2008 09:37:01 -0800, Tim Cross
<TimC...@discussions.microsoft.com> wrote:

>Possibly. How about a brief synopsis (maybe pseudo code like) of what I am
>doing:

[ snip ]

>Here I get ready to add the new address. Before I actually do this is where
>I would want to search ALL of my organization's proxy addresses to see if
>there may already be a match so I don't give the same address to two
>different mailboxes.

That's what the sample code did.

>Looping through almost 2000 mailboxes, the search needs to be quick or the
>above steps could take way to long to be usable.

You don't search the individual object, you let the LDAP query search
the indexed values.

>Make any more sense what it is I am trying to do? Even though I look mostly
>at X500 in above steps my actual routine is processing all X400, X500, as
>well as all SMTP addresses of all of my mailboxes.

The address type doesn't matter.

Add this at the top of your code (no need to keep creating the same
object over an over again):

$searcher = new-object DirectoryServices.DirectorySearcher

Add this where you're going to check for the address:

$addr = <whatever address you want to search for>
$filter = "(proxyaddresses=$addr)"

searcher.filter = $filter


esult = $null
result = $searcher.FindOne

if ($result -ne $null) # the address is used by something
{
# do whatever you want here
}
else # the address isn't in use
{
# do whtever you want here

Tim Cross

unread,
Dec 6, 2008, 11:52:01 PM12/6/08
to
Sorry it took so long to get back. I will give this a try in the morning and
let you know how it works. Thanks for the ideas, though.

Tim Cross

unread,
Dec 7, 2008, 8:42:01 AM12/7/08
to
This is close. With a little 'fixing' I can get it to find matches or not
find within the parent domain. It doesn't seem to be able to search the
child domain, though, as it is written.

Rich Matheisen [MVP]

unread,
Dec 7, 2008, 11:41:53 AM12/7/08
to
On Sun, 7 Dec 2008 05:42:01 -0800, Tim Cross
<TimC...@discussions.microsoft.com> wrote:

>This is close. With a little 'fixing' I can get it to find matches or not
>find within the parent domain. It doesn't seem to be able to search the
>child domain, though, as it is written.

No, as written, it just defaults to the domain in which its run. You
can, of course, change that by specifying the root of the search and
the scope.

Tim Cross

unread,
Dec 7, 2008, 5:18:08 PM12/7/08
to
What would be the easiest way to switch between parent and child while inside
my main loop that may get records from either domain at any point during the
loop?

Rich Matheisen [MVP]

unread,
Dec 7, 2008, 6:59:28 PM12/7/08
to
On Sun, 7 Dec 2008 14:18:08 -0800, Tim Cross
<TimC...@discussions.microsoft.com> wrote:

>What would be the easiest way to switch between parent and child while inside
>my main loop that may get records from either domain at any point during the
>loop?

Don't switch. Use the root domain and make sure the scope is
"SubTree".

Tim Cross

unread,
Dec 7, 2008, 7:18:01 PM12/7/08
to
That doesn't seem to allow me to search parent AND child. Should it?

Rich Matheisen [MVP]

unread,
Dec 7, 2008, 8:06:41 PM12/7/08
to
On Sun, 7 Dec 2008 16:18:01 -0800, Tim Cross
<TimC...@discussions.microsoft.com> wrote:

>That doesn't seem to allow me to search parent AND child. Should it?

To search across multiple domains you hae to use global catalog
servers, not domain controllers. Usually you can do that by changing
the "LDAP:" (which uses port 389) to "GC:" (which uses port 3268).

If it doesn't, you can always switch to the ADSI type adaptor.

Tim Cross

unread,
Dec 7, 2008, 9:43:01 PM12/7/08
to
Cool, using GC does seem to work. Now all I need to do is fine tune it a
little, try to make it a little faster, and see what I have.
Thanks for your all your help with this.

KeesG

unread,
May 19, 2009, 6:13:02 PM5/19/09
to
why not use the filter option:

get-mailrecipient -filter{(EmailAddresses -eq '<YourMailAddress>')}
-IgnoreDefaultScope -ReadFromDomainController

It will return an object if the mailaddres exists. it will return $null if
it is not found.


--
Kees de Groot

AlbaTom

unread,
Nov 5, 2009, 8:43:02 AM11/5/09
to
Thanks, Rich!
This helped me get over a hump !
I put it into a function that is called after the address is verified using
[Microsoft.Exchange.Data.SmtpAddress]

function checkSMTP($addr){
$result = $null
$searcher = new-object system.directoryservices.directorysearcher([ADSI]'')
$searcher.filter = "(&(proxyaddresses=*$addr*)(objectclass=user))"
$result = $searcher.FindOne()
if($result -ne $null){return $false}else{return $true}
}#checkSMTP

Rich Matheisen [MVP]

unread,
Nov 5, 2009, 10:33:00 PM11/5/09
to

Dunno if "Rich" was me, but using a filter that has a wildcard in it
and then using FindOne seems pretty risky. What if there are multiple
addresses that match the criterion?

E.g. searching for *s...@domain.com* might return these results if you
used FindAll:

s...@domain.com
as...@domain.com
bs...@domain.com

Since the order of the search isn't specified (or controlable) you
/might/ get back any one of them (and not always the same one) on
different searches.

0 new messages