Using the Script
The simple-to-use FindEmail.pl script assumes that the computer running the script is a member of an AD domain and that the user has permissions to submit LDAP queries. Run the script, passing in either a full email address or part of an address. You can also specify multiple addresses. For example,
perl FindEmail.pl droth@
windowsitpro.com admin
displays all user accounts that have an email or proxy address containing either droth@windowsitpro.com or admin (e.g., admin@mycompany .com,john.doe@administration.com). If you know a specific address path to use, you can speed up your search. However, unless you're a systems administrator or Exchange administrator,
you probably don't know this information. The example
perl FindEmail.pl
-a "OU=Sales,OU=Departments"
-s MyServer
discounts@mycompany.com
searches for discounts@mycompany .com but only in the Sales OU and any subcontainer. The script connects to MyServer to perform the query.
How the Script Works
The FindEmail.pl script uses COM to interact with both ADODB and ADSI. Therefore, it has to use the Win32::OLE extension (which provides Windows COM functionality). Listing 1 an excerpt of the FindEmail.pl script, uses Win32::OLE to obtain a COM object that represents an ADSI connection to AD. The call to Win32::OLE-> GetObject() is interesting because it doesn't specify a COM class ID, as you would normally do when accessing a COM object. However, ADSI registers several COM monikers that take the place of a COM class ID. In this case, the LDAP:// moniker invokes ADSI. The LDAP://$Config{server}RootDse string tells COM to invoke ADSI and connect to AD's root Directory Systems-Agent Specific Entry (DSE). Think of DSE as the top level of your AD implementation. If the user runs the script and specifies a server to use (by using the -s switch), the string will look like LDAP://your_server/RootDse.
Listing 1 continues by calling into the FindEmailAddressAccount() subroutine, which performs an account search for each email address that the user has specified. The code then passes the results of the search into the Display() subroutine to present the data to the user.
The FindEmailAddressAccount() subroutine, which Listing 2 shows, performs the email address lookup and maps them to accounts. First, it retrieves the default naming context (i.e., a text string that ADSI uses to determine where in AD to start the search) from the AD server. Typically, the default naming context represents the top level of the AD tree. For example, a domain called MyDomain.com would result in a Default Naming Context of "DC=MyDomain,DC=com".
Next, the subroutine creates the query that it will submit to AD. Here is where the code uses the default naming context. If the user specified an address path, the path is prepended to the naming context. The script then creates a generic ADODB connection object, configures it to use the ADSI provider, and uses it to execute the query. If the query is successful, it returns an ADODB recordset object ($Record) that contains the query results. For each database record returned in the record set, the script retrieves an ADSI account object by passing the record's ADsPath value (the only field that the query requested) into Win32::OLE->
GetObject(). The account is pushed onto an array and the While loop tells the recordset to move to the next record. This process continues until the $Record object indicates that it has hit the End Of File (EOF)—that is, $Record->EOF no longer equals zero. At this point, the $Record object has no more records left to process.
The Display() subroutine loops through each ADSI account object in the $AccountList array reference passed into the routine. For each of these accounts, the Exchange proxy-Addresses property is examined. Commonly, the proxyAddresses value is an array of email addresses prefixed with the addresses' protocol. However, in some cases, the property might not contain an array of addresses but instead a single address. Listing 3 manages these cases by checking whether the property is an array. If the property is an array, the code dereferences the property, casting it into an array context and pushing array entries onto a temporary @ProxyList array. If the property is a single address, the code pushes it directly onto the @ProxyList array.
The script then processes the list of email addresses. The list consists of both the addresses in the @ProxyList array (essentially, the list of proxyAddresses) and the address from the AD mail property. Typically, the mail address is already in the proxyAddresses list, so a duplicate might occur in the resulting displayed list.
However, sometimes these addresses are mutually exclusive.