param([string]$CSVFileName,[string]$EmailAddress,[string]$Username,[string]$Password,[string]$Domain,[bool]$Impersonate,[string]$EwsUrl,[string]$EWSManagedApiDLLFilePath,[bool]$Exchange2007);
#
# Import-MailboxContacts.ps1
#
# By Steve Goodman, Use at your own risk.
# 17/12/15 Edited by Chris Prevel to run on Exchange 2013, using EWS 2.1 API
# Added settings to run through proxy, changed mappings to match powershell export of contacts, changed dll path, updated attributes
#
# Parameters
# Mandatory:
# -CSVFileName : Filename of the CSV file to import contacts for this user from. Same format as Outlook Export.
# -EmailAddress : Account SMTP email address. Required, but only used when impersonating or with Autodiscover - otherwise uses the user you login as
# Optional:
# -Impersonate : Set to $true to use impersonation.
# -Username : The username to use. If this isn't specified (along with Password), attempts to use the logged on user.
# -Password : Used with above
# -Domain : Used with above - optional.
# -EwsUrl : The URL for EWS if you don't want to use Autodiscover. Typically https://casserver/EWS/Exchange.asmx
# -EWSManagedApiDLLFilePath : (Optional) Overwrite the filename and path to the DLL for EWS Managed API. By default, uses the default install location.
# -Exchange2007 : Set to $true to use the Exchange 2007 SP1+ version of the Managed API.
#
# Contact Mapping - this maps the attributes in the CSV file (left) to the attributes EWS uses.
# NB: If you change these, please note "FirstName" is specified at line 102 as a required attribute and
# "FirstName" and "LastName" are hard coded at lines 187-197 when constructing NickName and FileAs.
$ContactMapping=@{
"FirstName" = "GivenName";
"MiddleName" = "MiddleName";
"LastName" = "Surname";
"CompanyName" = "CompanyName";
"Department" = "Department";
"JobTitle" = "JobTitle";
"BusinessAddressStreet" = "Address:Business:Street";
"BusinessAddressCity" = "Address:Business:City";
"BusinessAddressState" = "Address:Business:State";
"BusinessAddressPostalCode" = "Address:Business:PostalCode";
"BusinessAddressCountry" = "Address:Business:CountryOrRegion";
"HomeAddressStreet" = "Address:Home:Street";
"HomeAddressCity" = "Address:Home:City";
"HomeAddressState" = "Address:Home:State";
"HomeAddressPostalCode" = "Other:Home:PostalCode";
"HomeAddressCountry" = "Address:Home:CountryOrRegion";
"OtherAddressStreet" = "Address:Other:Street";
"OtherAddressCity" = "Address:Other:City";
"OtherAddressState" = "Address:Other:State";
"OtherAddressPostalCode" = "Address:Other:PostalCode";
"OtherAddressCountry" = "Address:Other:CountryOrRegion";
"AssistantTelephoneNumber" = "Phone:AssistantPhone";
"BusinessFaxNumber" = "Phone:BusinessFax";
"BusinessTelephoneNumber" = "Phone:BusinessPhone";
"Business2TelephoneNumber" = "Phone:BusinessPhone2";
"CallbackTelephoneNumber" = "Phone:CallBack";
"CarTelephoneNumber" = "Phone:CarPhone";
"CompanyMainTelephoneNumber" = "Phone:CompanyMainPhone";
"HomeFaxNumber" = "Phone:HomeFax";
"HomeTelephoneNumber" = "Phone:HomePhone";
"Home2TelephoneNumber" = "Phone:HomePhone2";
"ISDNNumber" = "Phone:ISDN";
"MobileTelephoneNumber" = "Phone:MobilePhone";
"OtherFaxNumber" = "Phone:OtherFax";
"OtherTelephone" = "Phone:OtherTelephone";
"PagerNumber" = "Phone:Pager";
"PrimaryTelephoneNumber" = "Phone:PrimaryPhone";
"RadioTelephoneNumber" = "Phone:RadioPhone";
"TTYTDDTelephoneNumber" = "Phone:TtyTddPhone";
"TelexNumber" = "Phone:Telex";
"Anniversary" = "WeddingAnniversary";
"Birthday" = "Birthday";
"Email1Address" = "Email:EmailAddress1";
"Email2Address" = "Email:EmailAddress2";
"Email3Address" = "Email:EmailAddress3";
"Initials" = "Initials";
"OfficeLocation" = "OfficeLocation";
"ManagerName" = "Manager";
"Body" = "Body";
"Profession" = "Profession";
"Spouse" = "SpouseName";
"WebPage" = "BusinessHomePage";
"Contact Picture File" = "Method:SetContactPicture"
}
[System.Net.WebRequest]::DefaultWebProxy = $null
# CSV File Checks
# Check filename is specified
if (!$CSVFileName)
{
throw "Parameter CSVFileName must be specified";
}
# Check file exists
if (!(Get-Item -Path $CSVFileName -ErrorAction SilentlyContinue))
{
throw "Please provide a valid filename for parameter CSVFileName";
}
# Check file has required fields and check if is a single row, or multiple rows
$SingleItem = $false;
$CSVFile = Import-Csv -Path $CSVFileName;
if ($CSVFile."First Name")
{
$SingleItem = $true;
} else {
if (!$CSVFile[0]."FirstName")
{
throw "File $($CSVFileName) must specify at least the field 'First Name'";
}
}
# Check email address
if (!$EmailAddress)
{
throw "Parameter EmailAddress must be specified";
}
if (!$EmailAddress.Contains("@"))
{
throw "Parameter EmailAddress does not appear valid";
}
# Check EWS Managed API available
if (!$EWSManagedApiDLLFilePath)
{
$EWSManagedApiDLLFilePath = "C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.1\Microsoft.Exchange.WebServices.dll"
}
if (!(Get-Item -Path $EWSManagedApiDLLFilePath -ErrorAction SilentlyContinue))
{
throw "EWS Managed API not found at $($EWSManagedApiDLLFilePath). Download from http://www.microsoft.com/download/en/details.aspx?id=28952";
}
# Load EWS Managed API
[void][Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.1\Microsoft.Exchange.WebServices.dll");
# Create Service Object
if ($Exchange2007)
{
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
} else {
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
}
# Set credentials if specified, or use logged on user.
if ($Username -and $Password)
{
if ($Domain)
{
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Username,$Password,$Domain);
} else {
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Username,$Password);
}
} else {
$service.UseDefaultCredentials = $true;
}
# Set EWS URL if specified, or use autodiscover if no URL specified.
if ($EwsUrl)
{
$service.URL = New-Object Uri($EwsUrl);
} else {
try {
$service.AutodiscoverUrl($EmailAddress);
} catch {
throw;
}
}
# Perform a test - try and get the default, well known contacts folder.
if ($Impersonate)
{
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress);
}
try {
$ContactsFolder = [Microsoft.Exchange.WebServices.Data.ContactsFolder]::Bind($service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts);
} catch {
throw;
}
# Add contacts
foreach ($ContactItem in $CSVFile)
{
# If impersonate is specified, do so.
if ($Impersonate)
{
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress);
}
$ExchangeContact = New-Object Microsoft.Exchange.WebServices.Data.Contact($service);
if ($ContactItem."FirstName" -and $ContactItem."LastName")
{
$ExchangeContact.NickName = $ContactItem."FirstName" + " " + $ContactItem."LastName";
}
elseif ($ContactItem."FirstName" -and !$ContactItem."LastName")
{
$ExchangeContact.NickName = $ContactItem."FirstName";
}
elseif (!$ContactItem."FirstName" -and $ContactItem."LastName")
{
$ExchangeContact.NickName = $ContactItem."LastName";
}
$ExchangeContact.DisplayName = $ExchangeContact.NickName;
$ExchangeContact.FileAs = $ExchangeContact.NickName;
$BusinessPhysicalAddressEntry = New-Object Microsoft.Exchange.WebServices.Data.PhysicalAddressEntry;
$HomePhysicalAddressEntry = New-Object Microsoft.Exchange.WebServices.Data.PhysicalAddressEntry;
$OtherPhysicalAddressEntry = New-Object Microsoft.Exchange.WebServices.Data.PhysicalAddressEntry;
# This uses the Contact Mapping above to save coding each and every field, one by one. Instead we look for a mapping and perform an action on
# what maps across. As some methods need more "code" a fake multi-dimensional array (seperated by :'s) is used where needed.
foreach ($Key in $ContactMapping.Keys)
{
# Only do something if the key exists
if ($ContactItem.$Key)
{
# Will this call a more complicated mapping?
if ($ContactMapping[$Key] -like "*:*")
{
# Make an array using the : to split items.
$MappingArray = $ContactMapping[$Key].Split(":")
# Do action
switch ($MappingArray[0])
{
"Email"
{
$ExchangeContact.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::($MappingArray[1])] = $ContactItem.$Key;
}
"Phone"
{
$ExchangeContact.PhoneNumbers[[Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::($MappingArray[1])] = $ContactItem.$Key;
}
"Address"
{
switch ($MappingArray[1])
{
"Business"
{
$BusinessPhysicalAddressEntry.($MappingArray[2]) = $ContactItem.$Key;
$ExchangeContact.PhysicalAddresses[[Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::($MappingArray[1])] = $BusinessPhysicalAddressEntry;
}
"Home"
{
$HomePhysicalAddressEntry.($MappingArray[2]) = $ContactItem.$Key;
$ExchangeContact.PhysicalAddresses[[Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::($MappingArray[1])] = $HomePhysicalAddressEntry;
}
"Other"
{
$OtherPhysicalAddressEntry.($MappingArray[2]) = $ContactItem.$Key;
$ExchangeContact.PhysicalAddresses[[Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::($MappingArray[1])] = $OtherPhysicalAddressEntry;
}
}
}
"Method"
{
switch ($MappingArray[1])
{
"SetContactPicture"
{
if (!$Exchange2007)
{
if (!(Get-Item -Path $ContactItem.$Key -ErrorAction SilentlyContinue))
{
throw "Contact Picture File not found at $($ContactItem.$Key)";
}
$ExchangeContact.SetContactPicture($ContactItem.$Key);
}
}
}
}
}
} else {
# It's a direct mapping - simple!
if ($ContactMapping[$Key] -eq "Birthday" -or $ContactMapping[$Key] -eq "WeddingAnniversary")
{
[System.DateTime]$ContactItem.$Key = Get-Date($ContactItem.$Key);
}
$ExchangeContact.($ContactMapping[$Key]) = $ContactItem.$Key;
}
}
}
# Save the contact
$ExchangeContact.Save();
# Provide output that can be used on the pipeline
$Output_Object = New-Object Object;
$Output_Object | Add-Member NoteProperty FileAs $ExchangeContact.FileAs;
$Output_Object | Add-Member NoteProperty GivenName $ExchangeContact.GivenName;
$Output_Object | Add-Member NoteProperty Surname $ExchangeContact.Surname;
$Output_Object | Add-Member NoteProperty EmailAddress1 $ExchangeContact.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1]
$Output_Object;
}