Skip to main content

EWS Contacts rollup Powershell module

In this post I'm going to try to rollup a number of different Contact Scripts I've posted over the past couple of years into one module that will hopefully make things a little easier to use when you want to do things with Contacts using EWS and Powershell

I've put the code for this script up in GitHub repo it's 1K+ lines and I hope to add a few more things to the script as I go (and fix bugs). But if anybody has idea's please use GitHub to submit them. You can download the script as a zip from here

So here's what it can do at the moment


This can be used to get a Contact from the Mailbox's default contacts folder, other contacts sub folder or the Global Address List eg to get a contact from the default contact folder by searching using the Email Address (This will return a EWS Managed API Contact object).

Example 1

Get-Contact -MailboxName -EmailAddress

This will search the default contacts folder using the ResolveName operation in EWS, it also caters for contacts that where added from the Global Address List in Outlook. When you add a contact from the GAL the email address that is stored in the Mailbox's contacts Folder uses the EX Address format. So in this case when you go to resolve or search on the SMTP address it won't find the contact that has been added from the GAL with this address. To cater for this the GAL is also searched for the EmailAddress you enter in (using ResolveName), if a GAL entry is returned (that has a matching EmailAddress) then the EX Address is obtained using Autodiscover and the UserDN property and then another Resolve is done against the Contacts Folder using the EX address.

Because ResolveName allows you to resolve against more then just the Email address I've added a -Partial Switch so you can also do partial match searches. Eg to return all the contacts that contain a particular word (note this could be across all the properties that are searched) you can use

Get-Contact -MailboxName -EmailAddress glen -Partial

By default only the Primary Email of a contact is checked when you using ResolveName if you want it to search the multivalued Proxyaddressses property you need to use something like the following

Get-Contact -MailboxName -EmailAddress -Partial

Or to search via the SIP address you can use

Get-Contact -MailboxName -EmailAddress -Partial

(using the Partial switch is required in this case because the EmailAddress your search on won't match the PrimaryAddress of the contact so in this case also you can get partial matches back).

There is also a -SearchGal switch for this cmdlet which means only the GAL is searched eg

Get-Contact -MailboxName -EmailAddress -SearchGal

In this case the contact object returned will be read only (although you can save it into a contacts folder which I've used in another cmdlet).

Finally if your contacts aren't located in the default contacts folder you can use the folder parameter to enter in the path to folder that you want to search eg

Get-Contact -MailboxName -EmailAddress -Folder "\Contacts\SubFolder"


This can be used to create a contact, I've added parameters for all the most common properties you would set in a contact, some contact property need to be set via Extended properties (if you need to set this you can either add it in yourself or after you create the contact use Get-Contact and update the contact object).

Example 1 to create a contact in the default contacts folder

Create-Contact -Mailboxname -EmailAddress -FirstName John -LastName Doe -DisplayName "John Doe"

to create a contact and add a contact picture

Create-Contact -Mailboxname -EmailAddress -FirstName John -LastName Doe -DisplayName "John Doe" -photo 'c:\photo\Jdoe.jpg'

to create a contact in a user created subfolder

 Create-Contact -Mailboxname -EmailAddress -FirstName John -LastName Doe -DisplayName "John Doe" -Folder "\MyCustomContacts"

This cmdlet uses the EmailAddress as unique key so it wont let you create a contact with that email address if one already exists.


This Cmdlet can be used to update an existing contact the Primary email address is used as a unique key so this is the one property you can't update. It will take the Partial switch like the other cmdlet but will always prompt before updating in this case.

Example1 update the phone number of an existing contact

Update-Contact  -Mailboxname -EmailAddress -MobilePhone 023213421

Example 2 update the phone number of a contact in a users subfolder

Update-Contact  -Mailboxname -EmailAddress -MobilePhone 023213421 -Folder "\MyCustomContacts"


This Cmdlet can be used to delete a contact from a contact folders

eg to delete a contact from the default contacts folder

Delete-Contact -MailboxName -EmailAddress

to delete a contact from a non user subfolder

Delete-Contact -MailboxName -EmailAddress -Folder \Contacts\Subfolder


This cmdlet can be used to export a contact to a VCF file, this takes advantage of EWS ability to provide the contact as a VCF stream via the MimeContent property.

To export a Contact to a vcf use

Export-Contact -MailboxName -EmailAddress -FileName c:\export\filename.vcf

If the file already exists it will handle creating a unique filename

To export from a contacts subfolder use

Export-Contact -MailboxName -EmailAddress -FileName c:\export\filename.vcf -folder \contacts\subfolder


This cmdlet exports a Global Address List entry to a VCF file, unlike the Export-Contact cmdlet which can take advantage of the MimeStream provided by the Exchange Store with GAL Contact you don't have this available. The script creates aVCF file manually using the properties returned from ResolveName. By default the GAL photo is included with the file but I have included a -IncludePhoto switch which will use the GetUserPhoto operation which is only available on 2013 and greater.

Example 1 to save a GAL Entry to a vcf

Export-GalContact -MailboxName -EmailAddress -FileName c:\export\export.vcf

Example 2 to save a GAL Entry to vcf including the users photo

Export-GalContact -MailboxName -EmailAddress -FileName c:\export\export.vcf -IncludePhoto


This Cmdlet copies a contact from the Global Address list to a local contacts folder. The EmailAddress in used as a unique key so the same contact won't be copied into a local contacts folder if it already exists. By default the GAL photo isn't included but I have included a -IncludePhoto switch which will use the GetUserPhoto operation which is only available on 2013 and greater.

Example 1 to Copy a Gal contacts to local Contacts folder

Copy-Contacts.GalToMailbox -MailboxName -EmailAddress

Example 2 Copy a GAL contact to a Contacts subfolder

Copy-Contacts.GalToMailbox -MailboxName -EmailAddress  -Folder \Contacts\UnderContacts

Popular posts from this blog

Export calendar Items to a CSV file using EWS and Powershell

Somebody asked about this last week and while I have a lot of EWS scripts that do access the Calendar I didn't have a simple example that just exported a list of the Calendar events with relevant information to a CSV file so here it is. I've talked on this one before in this howto  but when you query the calendar folder using EWS you need to use a CalendarView which will expand any recurring appointments in a calendar. There are some limits when you use a calendarview in that you can only return a maximum of 2 years of appointments at a time and paging will limit the max number of items to 1000 per call. So if you have a calendar with a very large number of appointments you need to break your query into small date time blocks. In this example script I'm just grabbing the next 7 days of appointments if you want to query a longer period you need to adjust the following lines (keeping in mind what I just mentioned) #Define Date to Query $StartDate = (Get-Date) $EndDate

Downloading a shared file from Onedrive for business using Powershell

I thought I'd quickly share this script I came up with to download a file that was shared using One Drive for Business (which is SharePoint under the covers) with Powershell. The following script takes a OneDrive for business URL which would look like This script is pretty simple it uses the SharePoint CSOM (Client side object Model) which it loads in the first line. It uses the URI object to separate the host and relative URL which the CSOM requires and also the SharePointOnlineCredentials object to handle the Office365 SharePoint online authentication. The following script is a function that take the OneDrive URL, Credentials for Office365 and path you want to download the file to and downloads the file. eg to run the script you would use something like ./spdownload.ps1 '

The MailboxConcurrency limit and using Batching in the Microsoft Graph API

If your getting an error such as Application is over its MailboxConcurrency limit while using the Microsoft Graph API this post may help you understand why. Background   The Mailbox  concurrency limit when your using the Graph API is 4 as per . This is evaluated for each app ID and mailbox combination so this means you can have different apps running under the same credentials and the poor behavior of one won't cause the other to be throttled. If you compared that to EWS you could have up to 27 concurrent connections but they are shared across all apps on a first come first served basis. Batching Batching in the Graph API is a way of combining multiple requests into a single HTTP request. Batching in the Exchange Mail API's EWS and MAPI has been around for a long time and its common, for email Apps to process large numbers of smaller items for a variety of reasons.  Batching in the Graph is limited to a m
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.