Using Powershell to import contacts into Exchange and Outlook Live

When performing migrations between different systems, there’s always the case where the tools available don’t do the job out of the box – and although IMAP migration tools for Exchange and Outlook Live can be great for moving mail, there isn’t a decent free solution for importing contacts.

For a recent migration from a Unix system (Dovecot + SquirrelMail) to Outlook Live, I came across this very scenario. While Microsoft provide IMAP migration tools to move mail to Outlook Live (which I was lucky enough to beta test before it was widely available), no tools are provided to move other data such as contacts and calendars.

While this isn’t the actual code I used (I wrote my original code in C#), I’ve re-visited what I’ve done and listened to what others say they need. What I’ve heard is it would be useful to have some Powershell code that out-of-the box can import contacts into any Exchange mailbox. The reason that Powershell is the right language for code like this is that it’s fairly easy for the enterprising administrator to modify to their needs.

Getting started

Before you can run this script, there are a few things you need to set up first. Don’t worry though! It’s nothing too onerous – all is needed to get going is two things:

  1. Setup of EWS  impersonation, unless you only want to work with accounts you know the username/password for.
  2. Installing the Managed API DLL onto your computer.

Setup of Exchange Web Services Impersonation
Exchange Web Services is the programmatic interface to each user’s Exchange mailbox. Most actions that can be performed in Outlook can be performed via EWS – so much so, in fact, that Apple’s in Snow Leopard and the latest update for Entourage 2008 use EWS as the backend for the mail clients themselves.

If you’re planning on doing a mass-import of contacts, or don’t know the user’s password you’re importing, then setup of EWS impersonation is the step you need to take to allow a trusted account to switch to the user you want to import.

In Exchange 2010, setup of Exchange impersonation is managed via RBAC. Full details of how to setup impersonal are on the Microsoft site, but if you just want to get it setup for a single admin/service account, org-wide, use the following command substituing serviceaccount for your service account:

New-ManagementRoleAssignment -Name:impersonationAssignmentName -Role:ApplicationImpersonation -User:serviceaccount

On Exchange 2007, it’s very different, and is managed by AD permissions on individual Client Access Servers. Again – full details on the Microsoft site, but to add the permission to all CAS servers, the following code will suffice, again substituting serviceaccount for your Service account:

Get-ExchangeServer | where {$_.IsClientAccessServer -eq $TRUE} | ForEach-Object {Add-ADPermission -Identity $_.distinguishedname -User (Get-User -Identity serviceaccount| select-object).identity -extendedRight ms-Exch-EPI-Impersonation}

Installing the Exchange Web Services Managed API
Next, whatever environment you are in, you need a copy of the DLL file that provides the bits and pieces that make this all work. The easiest way to get up and running is to download the API (choosing the right version for your platform), and install it to it’s default location.

Download the EWS Managed API v1.2 from the Microsoft site

Once downloaded and installed, you should be good to go with script.

Using the script Import-MailboxContacts.ps1

So, you’ve got impersonation setup if needed, got the EWS DLL on your machine. You should be good to go!

For each mailbox you want to import contacts from you need a separate CSV file. The format of the file is intentionally the same as Outlook will export in, mainly because a lot of apps already export in the format (Gmail does, for example) so you should find it easy to get test data, but if you haven’t I’ve included a sample file to get you started.

Along with the data, you also need, at a minimum, the mailbox email address to import to. This is used when impersonating, and for Autodiscover. If you’re not logged on as the user you want to use for the import, you can specify a username and password. Additionally, there’s a variety of options to specify the EWS Url manually, switching to the Exchange 2007 version of the API etc.


The first example is a straightforward import into the current logged-on user’s mailbox. We’re specifying the Email Address and the URL to EWS (to bypass Autodiscover):


.\Import-MailboxContacts.ps1 -CSVFileName .\Contacts.csv -EmailAddress -EwsUrl https://server/EWS/Exchange.asmx

As you can see in the above example – it’s all fairly straightforward. You’ll also see the output shows the contacts that have been created – you can use standard Powershell pipeling to export this data, pipe it to another command or filter it.

The second example is slightly more complicated, and reflects the main use case. We’re connecting to a remote exchange organisation, using Autodiscover to find the EWS address, enabling impersonation and providing credentials at the command line:


.\Import-MailboxContacts.ps1 -CSVFileName .\Contacts.csv –EmailAddress -Impersonate $true -Username serviceaccount -Password password -Domain contoso

In addition to the options above, you can also specify the parameters -Exchange2007 $true and use -EWSManagedApiDLLFilePath to specify a different path the the EWS DLL.

Powershell Code

Finally, you’ll need a copy of the code to do all this. Below you’ll find a ZIP file containing the Import-MailboxContacts.ps1 file and a sample CSV file. Happy importing!

Download as ZIP

99 thoughts on “Using Powershell to import contacts into Exchange and Outlook Live

  1. Hi Steve, really awesome script! Can you tell me how i can import csv’s with german umlauts (äöü), think there must be a code snippet with …”encoding” or something like that.

    Thanks in advance,

  2. Pingback: Importing Personal Contact CSV exports to Users’ mailboxes | BGCB & OMFIG

  3. Pingback: Contour(コンツアー) サーフボードマウントベース #3562 《納期約2週間》:カ

  4. Pingback: 【クーポンで3000円オフ★12日10時~16日14時】2段ベッド 二段ベッド ベッド キッ

  5. Pingback: 【メーカー直送品】コンセント×引き出し収納2杯×シンプルなデザイン

  6. Steve what I need to do is similar we have a shared group contact list and I want to sync this to a contacts folder in a number of users mailboxes (a dedicated contacts folder in each account not the main contacts folder) this is to allow a centrally administered list be available to a group of users in outlook, web mail and most importantly on mobile devices (running outlook ios)


  7. Pingback: 【北海道?沖縄?その他離島は発送不可】【送料無料】Na Kids Picc's トイボックスToy B

  8. Hi, thanks for the script.
    You can prompt as through EWS add information to create contacts on certificates S / MIME.
    The property has a $ ExchangeContact UserSMIMECertificate, but it ReadOnly.


  9. Hi Steve

    First off; Thanks a bunch for this script, its exactly what i was looking for!

    My usage case is as follows:

    Our support department are useing mobil phones for all calls and they would like to know, before answering, who’s calling – this can be achived by adding a contacts folder from the exchange integration we run with iPhones.

    I’ve successfully extracted the needed information from all users on our domain and exported it into a correcylt formatted .csv file.

    I’ve even managed to import it into my contacts folder – works like a charm!

    My problem is that i would like to create a subfolder with the contacts extracted from our AD, so as to not interfere with their already saved contacts.

    Could you point me in the right direction, as C# and .net integration into powershell is something i’m not at all familiar with.

    All help is much apreciated! 🙂

  10. Pingback: Import Pst Outlook 2010 Powershell

  11. Steve, This looks and works really great. Do you have any suggestions on addressing those GAL items that use the “Hide from Global Address List” checkbox checked. We use quite a few of these for different reasons and when we use this script it populates all accounts in GAL including those users that are hidden from the GAL.


Comments are closed.