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:\pscripts\Interop.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()

Finally, you loop though the query results and invoke CDOEXM’s createmailbox on each user, printing an error or success result, and dispose of allocated resources. When invoking createmailbox, you’ll notice that one of the usage of .PSBase; this is important because it allows you to access the underlying .NET ADSI native object.

#
# LOOP THROUGH EACH PERSON IN THE QUERY RESULT
#

foreach($person in $people)
{
   $mailstore = $EXCHANGE_MAILSTORE
   [string]$dn = $person.properties.distinguishedname
   $domain_person=
      New-Object System.DirectoryServices.DirectoryEntry
      ("$DOMAIN/$dn", $DOMAIN_SERVICE_ACCOUNT,
        $DOMAIN_SERVICE_ACCOUNT_PASSWORD)

   #create the mailbox
      (CDOEXM.IMailboxStore:
       http://msdn2.microsoft.com/en-us/library/aa487566.aspx)
   $ASSEMBLY_TYPE.invokemember("createmailbox",$BINDING_FLAGS,
      $null,$domain_person.psbase.nativeobject,$EXCHANGE_MAILSTORE)

   $domain_person.psbase.commitchanges()

   if($domain_person.homeMDB -ne $null)
   {
      #force AD user update
      $domain_person.psbase.commitchanges

      #print the success
      Write-Host "Success: $dn"
   }
   else
   {
      #print the failure
      Write-Host "Error: $dn"
   }
   #close connections
   $domain_person.dispose | out-null
}

#
# CLOSE THE OPEN DOMAIN CONNECTION
#

$domain_query.dispose | out-null

The following figure shows output of the script.

Conclusion

Now that you have seen how it’s possible to create user mailboxes with Powershell, the door is now wide open to use CDOEXM to manage other facets of your Exchange 2003 servers such as deleting and moving mailboxes. As a developer or administrator who is gearing towards a migration from Exchange 2003 to Exchange 2007, this is a prime opportunity to get your hands on Powershell today and make your future development work much more productive and efficient. If you build further on what you’ve learned here, please let us know by emailing jonATshoberg.net.

About the Authors

Jon Shoberg is a senior developer for the Fisher College of Business at The Ohio State University. He has extensive experience in developing enterprise systems in e-commerce, web, and search domains on the LAMP, Java, and .NET platforms. Jon has previously contributed to books and industry publications as a technical reviewer and coauthor, respectively.

Eddie Willett is an independent consultant specializing in Microsoft technologies. Powershell has become a recent favorite of his and would love to hear your feedback: eddieATshoberg.net.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read