Importing PSTs into Exchange 2010, The Easy Way

PST Importing has always been a bit messy. With Exchange 2010's Personal Archiving feature, it's become more pertinent, yet still comes with pit-falls, gotchas, and inexplicable errors. James Allison has done some research, and presents an easy way to smoothly tackle the whole problem.

The process of importing multiple users’ PST files into Exchange 2010 is not as simple as perhaps you might expect, and certainly not as simple is probably should be, given how common this particular task is. To try and spread the knowledge about wrestle with this task, this article is aimed at SysAdmins wanting to migrate their users’ personal PST files into their (the users’) main exchange mailboxes. Even better, to make this as easy as possible, I’ll walk through the entire process involved, as well as creating the appropriate PowerShell scripts to semi-automate the process. Finally, to keep everything clear, I’ve split the material into three parts:

  • Importing a single PST File into Exchange 2010 RTM and SP1
  • Finding PST files on your network, and then…
  • …Importing these into Exchange (i.e. not one-by-one!)

While my solution is not necessarily Best Practice, it’s one of the best solutions I could research, and so it’s likely that many SysAdmins will come up with something similar. What you should bear in mind is that these three components I’ve described are not actually the relative “Easiest Way” of handling this importing process, as they require a non-trivial amount of tweaking, and come with their fair share of pitfalls and gotchas. The Really Easy Way is mentioned later in the article, and is, as far as I’ve found, the most painless way of handing PST imports with Exchange 2010.

Introduction:

Just so we’re all on the same page, this guide has focused on using Windows Management Instrumentation (WMI) to identify files on remote user’s machines, and then import these files into their mailboxes. There are of course several options:

  1. You could ask users to manually drag mails across from within outlook.
  2. You could have group policy enforce a logon script that copies user PST files to a shared network drive and then removes said files from their system (or prevents outlook from mounting it).
    A script running on a server can then poll for new PSTs in this folder and automatically add them with the -IsArchive parameter so that the contents of the users’ local archive PSTs are available in their archive mailboxes (almost) immediately. The advantages of this approach are that you don’t need to worry about locked files (as the files can be copied before outlook has had a chance to start/lock them), or enabling WMI firewall access on client machines. However, it does still require that the user log off and on…
  3. The third (and, I think, easiest) approach is to use WMI to remotely search for files. This can generate a list of PSTs on all machines, and highlight the machines which couldn’t be searched (and which would require further attention). However, it’s highly likely that Outlook will be running on your users’ machines, making this process trickier. Naturally, WMI can be used to terminate the Outlook process remotely, but this is not ideal, and there are other ways around this problem. The advantages of this approach is that it does not require individual users to login and out (useful if a user is on holiday, for instance) – merely that the machine is on (which could be managed via Wake On LAN).

As stated, this guide focuses on the WMI-based solution and just covers the basics – more advanced scripts could be created to deal with a greater variety of error cases and configurations (e.g. shutting down outlook, making separate lists of machines to try again, detailing which PSTs had passwords and could not be imported).

How to import a PST file into Exchange.

Importing a PST file into Exchange 2010 requires the use of the Exchange Management Shell (EMS), although (somewhat confusingly) this functionality was originally included in the Exchange Management Console in the Beta release of Exchange 2010.

A PowerShell cmdlet in the EMS is used to perform the action, and the use of this cmdlet requires that the current user has Import Export roles enabled on their profile. In order to run the import and export cmdlets, Exchange 2010 RTM also requires that Outlook 2010 x64 is installed on the machine being used to run said cmdlets, although this is no longer a requirement of Exchange 2010 SP1.

So, to import a single PST file into an exchange 2010 mailbox:

  1. Install Outlook 2010 x64 on the Exchange server. Bear in mind that, by default, on a machine with no pre-existing Office installation, the DVD’s autorun setup will try to install the x86 applications. Be sure to manually run the installer rom the x64 directory to install the x64 version of Outlook, although this step is not necessary for Exchange 2010 SP1, as this now (re)includes a MAPI provider.
  2. Enable Import Permissions for a security group which your user belongs to – In this case, ‘Mailbox Support’ – with the following command:

  3. Import the desired PST file into the appropriate user’s mailbox with the following command:

Exchange 2010 SP1 differs a little, in that you don’t need to install Outlook 2010 x64, and rather than the synchronous Import-Mailbox cmdlet, the asynchronous New-MailBoxImportRequest can be used, which takes the form of:

The status of current requests can be viewed with the Get-MailboxImportRequest cmdlet, and completed requests can be cleared (or pending/In-progress requests cancelled) with the Remove-MailboxImportRequest cmdlet. One of the advantages of this new cmdlet, other than it being asynchronous, is that you can specify an additional -IsArchive parameter, which will import the PST directly into the users archive mailbox.

I did experience a few problems using these cmdlets during the brief time I spent doing research for this guide. The Exchange 2010 RTM Import-Mailbox on one system simply refused to play nicely, and kept throwing the following error:

Not a lot of help in itself, although a little Googling and experimentation revealed four main potential causes for this error:

  1. The appropriate role permissions has not been added to the users security profile.
  2. The version of MAPI being used has somehow got confused, which could be fixed by running the fixmapi command from the command prompt.
  3. The PST file is password protected.
  4. There is a bug in exchange.

In my case, I’d unfortunately hit the forth problem, and the workaround proved to be pretty horrific – it may simply be worth waiting for a fix from Microsoft. To complete my task, I had to temporarily add a new domain controller to my network to host a new Exchange 2010 server. I then moved the target mailboxes (i.e. the ones for which I had PSTs to import) across to this new server, performed the import, and then moved the mailboxes back to their original Exchange server and removed the temporary server from the network (Like I said, pretty horrific).

Upgrading the system to 2010 SP1 and using the New-MailBoxImportRequest cmdlet on the same system yielded the following error:

Again, this appears to be a known issue, and apparently one which is scheduled to be fixed before the final release of SP1.

Finding PST files on the network

So, we’ve seen the process for importing a local PST file into Exchange server, however, in reality, it’s likely that these PST files are scattered liberally around your network on the hard-drives of your users’ machines as a result of Outlook’s new personal archiving functionality. Ideally, so that this mass-import process is transparent to your users, you’d like some way of finding all of these PST files, pairing them up with their users, and then simply importing them into the appropriate mailbox.

There are a few steps required to set up something like that. First, we can query Active Directory for a list of all the machines attached to your domain. We can then use WMI to search each of these machines for PST files, and the file paths for these PSTs should hopefully give us a clue as to which user they belong to (by default, they will be created in a directory path containing the username.) We can also grab the file owner file attribute, which should correlate with the details in the file path.

Naturally, this technique requires that all of the machines in your network are switched on and accessible by WMI, although a list of the machines which could not be queried can be provided as an output.

Notes about WMI

By default, WMI is blocked by the windows firewall in Windows 7 and 2008 R2, so you’ll probably need to open up the ports on all of your users’ machines. This can be done with the netsh command, or through a change to group policy.

You might quite rightly be asking yourself “What are the implications of this?” WMI is a powerful beast which allows remote access to many aspects of a user’s machine. As such, it could be considered a significant security vulnerability. In addition, it’s typically accessed though port 135, which not only permits access to WMI, but also to any other DCOM components which may be installed on a machine, thus opening the way for exploitation by Trojans and the like. Needless to say, the ports are blocked by default for a reason, so carefully consider all of the implications when opening them.

WMI will also not help you if the machines you wish to tinker with are subject to NAT (Network Address Translation) – You’ll simply be unable to reach these machines.

Nevertheless, let’s assume a situation without any NAT, and where the security risks have been minimised. The following script generates a txt file (the filename defined on line 2) of all the computers on your domain to be searched. This file can then be manually edited with notepad to remove any machines you don’t wish to search:

Listing 1 – A PowerShell script to generate a list of all machines on your domain which are to be searched for PST files.

The next script will generate a CSV (Comma separated values) file detailing the network paths of the PST files you need to import:

Listing 2 – A PowerShell script to find and list network paths for PST files to be imported.

This script will take as input a text file containing a list of machine names, which is, conveniently, the output of the first script. It will then generate a .csv file of all the PST files found on those machines, and the owners associated with them. So far, so painless.

Importing the remote PSTs into Exchange

Now that we’ve seen how to gain a list of machines and their respective PST files, we now need to import these files into Exchange. The following script does just that:

Listing 3 – PowerShell to import a list of PST files into Exchange from their respective machines.

The yellow highlighted text shows the Exchange 2010 RTM Cmdlet, and the red shops the Exchange 2010 SP1 (delete as appropriate).

The Exchange 2010 SP1 version of the script will execute in far less time than the original RTM version due to the asynchronous nature of the ImportRequest cmdlet. These requests are processed in the background and can be monitored with the Get-MailboxImportRequest cmdlet to observe their status. Once these have completed, as mentioned earlier, it’s necessary to actively clear the requests with the Remove-MailboxImportRequest cmdlet. As easy as this all sounds, there are quite a few potential pitfalls here:

  • The users’ machines must be on,
  • File sharing must be on to allow for the file to be transferred,
  • Outlook must not be running on the remote users’ machines – If outlook is running and has the PST file attached, then the file will be locked and unavailable for importing,
  • Passwords are not supported – The PowerShell cmdlet used by exchange to import PST files simply doesn’t handle passwords.
  • There’s a limit on concurrent requests – With the SP1 asynchronous requests, no more than 10 concurrent requests can be handled per mailbox without manually specifying a unique name for each request (this makes the script a little more complicated, but is not a showstopper, particularly given that most users will only have a single errant PST file to be imported.)

That being said, there are various things you could to augment this script; some suggestions include:

  • Having WMI shut down Outlook on remote users’ machines before attempting import.
  • Generating a further output file detailing a list of all the PSTs which failed to import, with reasons why. It would be useful to know if these files were password protected, or the machine hosting them was shut down or had disconnected since they were identified.
  • In the SP1 case, you could automate the polling of the requests statuses, and the removal of those which have completed.

Summary

So, although it’s possible to search for an import your users’ PST files into Exchange from across the network, it’s not an easy or particularly well-documented process. Frustratingly, there are also elements of the process which are directly hampered by errors and glitches.

Although none of these problems are show-stoppers, they’ll raise your blood pressure if you don’t know about them! Hopefully this guide will set you on the right track and steer you around all but the most well-concealed pitfalls.

The Really Easy Way

As I mentioned at the start, although I’ve broken down the whole process into easy-to-follow steps and pointed out where you’ll need to pay extra attention, this is not, in fact, the easiest way of handling the PST Import process. If you’d rather negate the whole problem in one fell swoop, then there are 3rd party tools which will handle the whole import process for you in a quickly and smoothly, and which will allow you to manage every aspect the import at your convenience.

Resources:

Whilst I was investigating the background facts for this article, I found the following resources on the internet to be of interest:

At first I was Googling for ‘Importing PST files into Exchange’, the following pages on Experts Exchange and HowExchangeWorks.com proved to be an interesting read.

However, as stated in part 1 of this guide, one of the systems I was testing these processes on kept throwing errors when I was trying to execute the import-mailbox cmdlet. This page proved very helpful in identifying the issue I’d hit and suggesting a workaround.

I was then faced with the problem of actually locating the PST files on the network; I found a handy page on the MSExchangeTips blog, detailing how to query WMI for network.

Finally, as I was pretty new to PowerShell – the following pages all proved quite useful in getting me up to speed: