Enterprise Powershell: Creating Mailboxes in Exchange 2003
This articles focus on the increasingly popular Powershell command line shell and scripting language that runs on existing and future Microsoft infrastructure environments. We'll presume you are familiar with Powershell and have it installed and tested on your systems. If not, we encourage you to read an introductory article that will get you up to speed quickly.
Using Powershell with Exchange 2003
Let's consider a common mid-sized Microsoft IT environment for today with a few hundred mail-enabled active directory users. In this case, for email services you are a developer or systems administrator working with Exchange 2003 running on Windows Server 2003 who is using Powershell today in preparation for your future scripting needs with Exchange 2007 running on Windows Server 2008. Although there are a number of great ways Exchange 2007 and Powershell integrate, you must deal with a few hurdles in scripting Powershell and Exchange 2003 today. Specifically, you still must use CDOEXM as the fundamental component object model and interfaces used to manage the Exchange 2003 store.
As an Exchange 2003 developer or administrator, you are undoubtedly familiar with programming for the CDOEXM IMailboxstore interface and of course calling CreateMailbox. In fact, the Microsoft.com knowledgebase has a great article on how to accomplish this with C#. However, this is Powershell and if you have tried to translate the same examples you have probably received a message such as "Cannot load COM type CDOEXM.IMailBoxStore." We're going to show you how to get around this error by using CDOEXM through assembly reflection and late binding. If those two concepts escape your immediate memory, remember that assembly reflection is a way to view classes exposed from the assembly and late binding is binding to an object late as possible; this is most commonly just before it's called (run-time dynamic linking).
Powershell Mailbox Creation Script
Start with an initial snippet from your Powershell and Exchange 2003 script. Here, you are starting the script header and establishing default variables for Active Directory connectivity, domain query filter, and default exchange mail store. When searching for users, you are looking for all users in the domain who do not have their homeMDB property set—the message database where the mailbox is allocated. Keep in mind you'll want to tailor the filter criteria for your local policy where, commonly, only certain groups of users have mail-enabled accounts.
# # Powershell and Exchange 2003 Mailbox Creation # # # ACTIVE DIRECTORY DOMAIN CONNECTION # $DOMAIN = "LDAP://dc3.example.com:389" $DOMAIN_USER_BASE = "" $DOMAIN_SERVICE_ACCOUNT = "exchangemanager" $DOMAIN_SERVICE_ACCOUNT_PASSWORD = "XXXXXXXXX" $DOMAIN_SEARCH_FILTER = "(&(objectClass=user) (!homeMDB=*))" # # EXCHANGE 2003 MAIL STORES # $EXCHANGE_MAILSTORE = "CN=PEOPLE,CN=First Storage Group, CN=InformationStore,CN=EXCHMAIL0, CN=Servers, CN=First Administrative Group, CN=Administrative Groups,CN=EXAMPLECORP, CN=Microsoft Exchange,CN=Services, CN=Configuration,dc=example,dc=com";
Next, you have a set of references to CDOEXM that becomes a key point of the script. Here, you are loading the CDOEXM.dll, assigning the CDOEXM.IMailboxStore type to a variable, and setting the binding flags for invoking member methods. What this sets you up for is calling the CDOEXM createmailbox method.
# # CDOEXM REFERENCES # $ASSEMBLY = [Reflection.Assembly]::LoadFile ("C:pscriptsInterop.CDOEXM.dll") $ASSEMBLY_TYPE = $ASSEMBLY.GetType("CDOEXM.IMailboxStore") $BINDING_FLAGS = [Reflection.BindingFlags] "invokemethod,public"
Now, you query the Active Directory server for all users matching the specified filter.
# # QUERY ACTIVE DIRECTORY USERS WHO DO NOT HAVE A MAILBOX # $domain_query = new-Object System.DirectoryServices.DirectorySearcher $domain_query.searchroot = New-Object System.DirectoryServices.DirectoryEntry ("$DOMAIN/$DOMAIN_USER_BASE", $DOMAIN_SERVICE_ACCOUNT, $DOMAIN_SERVICE_ACCOUNT_PASSWORD) $domain_query.pagesize = 1000 $domain_query.searchscope = "subtree" $domain_query.filter = $DOMAIN_SEARCH_FILTER $people = $domain_query.findall()
Page 1 of 2