Adding Exchange 2007 mailboxes to existing user accounts

The most popular post on this blog continues to be Adding Exchange 2003 Mailboxes to Existing Accounts so I’m guessing this is something a lot of people need to do.

ATTENTION: PLEASE SEE this post INSTEAD for the basic method.

I hadn’t posted an Exchange 2007 method earlier because I haven’t needed to do it in production, and the ongoing pledge of my blog is that I do not theorise. I’m not promising you that my ways are the best or the most correct – just that I know work because I’ve done ’em.

Nonetheless I decided that, for this example, it was worth hitting the lab to see if my old method worked for 2007. I had assumed that all I would need to add to the process was a recipient-update powershell command…

but it didn’t work. Looks like recipient-update only recognises accounts that already have mailboxes.

 Update: It does work now – see here.

So in this post I will now present a possible approach, with the caveat that this is only tested in the lab.

Overview

I have decided to approach this with a seperate XMA that will just deal with the mailbox provisioning. With the XMA I can call the powershell cmdlets I need as part of the import and export steps.

My Import routine involves running the get-user cmdlet to get a list of all users in a particular OU. If I find one with a RecipientType of “User” rather than “UserMailbox” I change it to “UserMailbox”. The export step then runs the enable-mailbox cmdlet against it.

This is very simple indeed, however it should be possible to extend the theory to more complex requirements. It should also be possible to add a disable-mailbox step if mailbox removal is also required.

Environment

ILM 2007 FP1 server in the same domain as the Exchange server.

Powershell and Exchange Management Console installed on the ILM server.

Note that I first tried this with the ILM server in a different forest to Exchange but I ran into trouble with authentication, in particular because the enable-mailbox cmdlet doesn’t have a -Credential option (why on earth not??) so I simplified with a single domain.

Instructions

1.  Generate the import file to use as the template

XMA’s need to import via a text file, and you need an example during the creation of the XMA. I plan to use the get-user cmdlet to generate the CSV for the import step, so first I need to do this manually and create the example file.

Run the following command in the Exchange Management Shell:

get-user -OrganizationalUnit "ou=Users,ou=MyOrg,dc=mydomain,dc=com"
| export-csv c:template.csv -notypeinformation

Now copy the template.csv file to a temporary location on the ILM server.

2.  Create the MA

In ILM, create a new MA of type Extensible Connectivity.

Create a Call-based, Import and Export MA.

You need to add a name for the dll now, but it doesn’t yet have to exist. I use the convention CSExtension_MAName.dll for this type of extension.

Select the template file that you created with the get-user cmdlet. The first row is a header row and the delimiter is the comma character.

On the Configure Attributes page, set the Guid as the anchor attribute.

And finally, set a suitable join rule. I happened to have the sAMAccountName in the metaverse already, so I joined on that.

Now save your MA.

3.  Create the Extension Projects

As this is an XMA we need a CS Extension, where we write our Import and Export routines. For this example we will need an MA Extension as well.

Create a Rules Extension project for the MA,

and also a Connected Data Source Extension.

Add the new projects into your Solution in Visual Studio.

4.  Code the CSExtension

This was the first time I had attempted to run powershell commands from VB.NET code. The first problem I ran into was that I couldn’t find System.Management.Automation.dll, which you need to add as a reference to your project. Eventially I found a help comment on a blog somewhere which included the command that extracts this dll from something called the GAC.

You need to copy the dll out of the GAC to your project folder, and then reference it in your project.

copy C:\windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll C:\path_to_project_folder

Once I’d sorted that out I wrote this code.

5.  Run an Import

Create an Import run profile. You will need to specify a name for the import file that will be generated by your CSExtension – I used import.csv, but it doesn’t really matter what name you use.

Once that is done you can run the Import and populate your CS. You should be able to see the import.csv file appear in your MaData/MAName folder.

If you have problems, check the Event Log for errors. Also try running the powershell commands manually from powershell on the ILM server, and using the same account as the ILM service.

6.  Create an Advanced Export Flow

Now for the bit where we change RecipientType, triggering the export routine from the CSExtension that will add the actual mailbox.

In the MAExtension project you created for this MA add the following code to the MapAttributesForExport sub:

        Select Case FlowRuleName
            Case "export_RecipientType"
                If csentry("RecipientType").Value = "User" Then
                    csentry("RecipientType").Value = "UserMailbox"
                End If
        End Select

Now add an advanced export flow rule for the RecipientType attribute.

The flow rule will have no input – nothing selected on the metaverse side. Obviously you can change this if you want the mailbox addition to depend on other attribtes in the metaverse.

7.  Synchronize

At this point you should be able to run a full sync. If you had any objects with RecipientType = “User” in your CS you should now see them change to “UserMailbox”.

Tip: to make a test, remove a mailbox from an existing test account using the disable-mailbox cmdlet, then re-import.

8.  Export

The export step is where the enable-mailbox cmdlet will actually be run against any changed objects. Hopefully you will now be able to see the change in Exchange Management Console.

Immediately follow up your Export with an Import. If there are no import errors you’re doing fine. If you see the error “exported change was not reimported” then you need to investigate – this will indicate a failed enable-mailbox attempt, as the object was exported as “UserMailbox” but reimported as “User”.

In Summary

Like I said at the top, I haven’t used this approach in production so I have no idea how it would scale. In some environments it may make far more sense to deal with the mailbox enabling outside of ILM – however I would defnitely be inclined to try this out in the real world. And apart from anything else, I now know how to write an XMA that triggers powershell cmdlets – that’s gotta be useful!

Postscript

Brett Wilson has used this method since I posted this, and had some comments about performance which the WordPress comment function didn’t like, so here is what he had to say:

If the ILM server does not have internet access you may notice that it can take over 20 seconds to provision each mailbox. The reason for this is that each time the ExportEntry method invokes the pipeline powershell tries to download the CRL to check the authenticode signature on the exchange management shell snapin.

To work around this behaviour first install Exchange 2007 SP1 Update Rollup 5 and then create a file called powershell.exe.config on your WINDOWSsystem32windowspowershellv1.0 folder. The powershell.exe.config file should contain the following:

<configuration>
<runtime>
<generatePublisherEvidenceenabled=false/>
</runtime>
</configuration>

It may even be benificial to just turn this off by default to prevent the need to download the CRL in any event as even if the system can find the CRL the code will still need to wait for it to download.

For more info check the following microsoft KB article: http://support.microsoft.com/kb/944752

Thanks Brett!