Script: Updating Recipients in Exchange Online (Office 365)


A very common request is to update recipients in Exchange Online and commonly many updates are required. Updating a few recipients in EXO can easily be done with the Office 365 Admin Portal or Exchange Admin Console (ECP), but due to human error can lead to mistakes. When more than a few recipients need updates, scripting is needed.

 

The script below will cover five key functions. 1) Connecting to Azure AD/EXO/O365, if not connected already, 2) Getting input from a CSV file, 3) Detecting the recipient type, 4) Updating the properties of an existing recipient, and 5) Creating a Contact when an existing recipient is not found.

1)    Connecting to Azure AD/EXO/O365

Before we can do anything in EXO/O365 we need to start a remote PowerShell session to Office 365. So at the very start of the script it will check to see if there is an existing open session to EXO. If one is not found, a new session will be created.

Before sessions can be created, the Azure AD PowerShell module must be installed on the system running this script. It can be downloaded from: https://go.microsoft.com/fwlink/p/?linkid=236297

The first line below, uses the Get-PSSession cmdlet to get and then filter all session to return a count of those that are “Open” and have the ConfigurationName of “*Microsoft.Exchange*”. If this cmdlet, with the filters, returns no results, then the New-PSSession cmdlet is called. When the New-PSSession cmdlet is used, the credentials of a user, with the required rights, must be supplied. These are requested via a secure pop-up using the Get-Credential cmdlet and saved to the $UserCredential variable.

Using the $Session variable we store the session information, including credentials. This is then used by the Import-PSSession cmdlet to create the session. Finally, the session is connected to using Connect-msolservice.

If (((Get-PSSession | ?{$_.State -Like "*Open*" -And $_.ConfigurationName -Like "*Microsoft.Exchange*"}).Count) -Eq 0) {

$UserCredential= Get-Credential

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $UserCredential -Authentication Basic -AllowRedirection

Import-PSSession $Session

Connect-msolservice -credential $UserCredential
}

2)    Getting input from a CSV file

The five lines in the script example below, will read a Recipients.csv file and then process each line using a ForEach loop. In this loop, three fields are displayed: FirstName, LastName, and Email.

In this script, it is assume the CSV as the following fields in it: FirstName, LastName, Role, Email, Phone, MobilePhone, HomePhone, WorkPhone, Comments, Address, City, State, Zip, ID. These, except for ID, can map directly to existing attributes and the ID field will be stored CustomAttribute1 in the full script.

The first line uses the Import-Csv cmdlet to read in the file and then pass it, via the | (pipe), to the ForEach loop.

Import-Csv "Recipients.csv" |
ForEach {
$FullName = $_.FirstName + " " + $_.LastName
Write-Host “Full name: $FullName”
Write-Host "Looking for: $($_.Email)" -ForegroundColor Cyan   }

3)    Detecting if a recipient exists

Now that we have a PS session to O365 and the first line of the CSV ready, we need to see if the recipient existing and then based on its type use the correct cmdlets to update it.

Using the Get-Recipient cmdlet with the Email attribute from the CSV file we can query EXO for a matching recipient. By adding “-ErrorAction SilentlyContinue” we hide the error if one is not found, which makes for a cleaner running script. The $Recipient variable, which is first set to $Null to ensure that the previous value isn’t used, is set by the Get-Recipient cmdlet.

$Recipient = $Null
$Recipient = Get-Recipient $_.Email -ErrorAction SilentlyContinue
If ($Recipient -eq $Null) {
Write-Host "`tRecipient not found, creating" -ForegroundColor Yellow }
Else {
Write-Host `t"Found: $($Recipient.Name)" -ForegroundColor Green }

4)    Updating the properties of an existing recipient

Assuming the recipient exists, we 1st need to find out what type of recipient it is. To do this the script will check the RecipientType property.

There are three RecipientType value, at least supported by this script: MailContact, MailUser, & MailMailbox. A MailContact type is for objects that are mail enable, but do not have a logon and have an external email address. A MailUser is for objects that have been mail enable, with an external email address, but do have a login to O365. Last, MailMailbox is for objects that have an EXO mailbox and O365 login.

For the first two types, the Set-Contact cmdlet is used to set most of the attributes. For MailContact objects, the Set-MailContact cmdlet is used to set the CustomAttribute1 attribute and other Exchange only related attributes. For MailUser objects, Set-MailUser is needed to update the Exchange attributes. For MailMailbox objects, Set-MailMailbox is used to update the Exchange attributes.

Using three IF statements, checking the $Recipient.RecipientType value, the script calls the correct cmdlets to update the attribute. The  -WarningAction 0 parameter is used to hide the yellow warning message when the attribute value doesn’t change, since the value is the same.

If ($Recipient.RecipientType -eq "MailContact") {

Set-Contact $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0
Set-MailContact $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0
}

If ($Recipient.RecipientType -eq "MailUser") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0
Set-MailUser $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0
}

If ($Recipient.RecipientType -eq "MailMailbox") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-MailMailbox $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0
}

5)    Creating a Contact when an existing recipient is not found

The last key part of this script is to create a Contact when a recipient is not found. This is done with the New-MailContact cmdlet, this script only creates Contacts for CSV entries that aren’t found.

Inside a ForEach loop, the current object\entry being processed can be referred to using the $_ object. The cmdlet below sets five attributes to the value in the CSV for the current line being processed.

New-MailContact -Name $FullName -DisplayName $FullName -ExternalEmailAddress $_.Email -FirstName $_.FirstName -LastName $_.LastName

Putting the parts together

There are three major sections of the script, the 1st connects to Office 365, the 2nd is the UpdateRecipient function, and 3rd is the Import-Csv “Recipients.csv” and ForEach loop. The loop in the 3rd part calls the 2nd part for each line in the CSV file.

In the 3rd (Import-Csv “Recipients.csv”) part it queries EXO using the Get-Recipient cmdlet and if one is not found, the New-MailContact cmdlet is used to create a new contact. If the recipient is found or after the New-MailContact cmdlet, the existing or new object and the current value from the CSV file is passed to the UpdateRecipient function.

Below are the key lines from the 3rd section of the script:

Import-Csv "Recipients.csv" |

ForEach {

$Recipient = Get-Recipient $_.Email -ErrorAction SilentlyContinue

If ($Recipient -eq $Null) {

Write-Host "`tRecipient not found, creating" -ForegroundColor Yellow

$FullName = $_.Preferred + " " + $_.LastName

New-MailContact -Name $FullName -DisplayName $FullName -ExternalEmailAddress $_.Email -FirstName $_.FirstName -LastName $_.LastName

$Recipient = Get-Recipient $_.Email

}

Else {

Write-Host `t"Found: $($Recipient.Name)" -ForegroundColor Green

}

UpdateRecipient $Recipient $_

}

 

The 2nd part is the UpdateRecipient function, below is a partial copy of that code.

Function UpdateRecipient ($Recipient, $Properties) {

Write-Host `t"UpdateRecipient: $($Properties.Email)" -ForegroundColor Cyan

$FullName = $Properties.FirstName + " " + $Properties.LastName

 

If ($Recipient.RecipientType -eq "MailContact") {

Set-Contact …

Set-MailContact …

}

If ($Recipient.RecipientType -eq "MailUser") {

Set-User …

Set-MailUser …

}

If ($Recipient.RecipientType -eq "MailMailbox") {

Set-User …

Set-MailMailbox …

}

}

 

Full script


# CSV: FirstName, LastName, Role, Email, Phone, MobilePhone, HomePhone, WorkPhone, Comments, Address, City, State, Zip, ID

 

# CustomAttribute map [EXO = CSV]

# CustomAttribute1 = ID

 

# Connect to Office 365, if not connected

# Requires Azure AD PowerShell Module: https://go.microsoft.com/fwlink/p/?linkid=236297

If (((Get-PSSession | ?{$_.State -Like "*Open*" -And $_.ConfigurationName -Like "*Microsoft.Exchange*"}).Count) -Eq 0) {

$UserCredential= Get-Credential

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $UserCredential -Authentication Basic -AllowRedirection

Import-PSSession $Session

connect-msolservice -credential $UserCredential

}

 

Function UpdateRecipient ($Recipient, $Properties) {

Write-Host `t"UpdateRecipient: $($Properties.Email)" -ForegroundColor Cyan

$FullName = $Properties.FirstName + " " + $Properties.LastName

 

If ($Recipient.RecipientType -eq "MailContact") {

Set-Contact $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-Contact $Properties.Email -Phone $Properties.phone -MobilePhone $Properties.mobilephone -HomePhone $Properties.homephone -OtherTelephone $Properties.workphone -WarningAction 0

Set-Contact $Properties.Email -StreetAddress $Properties.address -City $Properties.city -StateOrProvince $Properties.state -PostalCode $Properties.zip -Title $Properties.Title -Notes $Properties.comments -WarningAction 0

Set-MailContact $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0

}

If ($Recipient.RecipientType -eq "MailUser") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-User $Properties.Email -Phone $Properties.phone -MobilePhone $Properties.mobilephone -HomePhone $Properties.homephone -OtherTelephone $Properties.workphone -WarningAction 0

Set-User $Properties.Email -StreetAddress $Properties.address -City $Properties.city -StateOrProvince $Properties.state -PostalCode $Properties.zip -Title $Properties.role -Notes $Properties.comments -WarningAction 0

Set-MailUser $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0

}

If ($Recipient.RecipientType -eq "MailMailbox") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-User $Properties.Email -Phone $Properties.phone -MobilePhone $Properties.mobilephone -HomePhone $Properties.homephone -OtherTelephone $Properties.workphone -WarningAction 0

Set-User $Properties.Email -StreetAddress $Properties.address -City $Properties.city -StateOrProvince $Properties.state -PostalCode $Properties.zip -Title $Properties.role -Notes $Properties.comments -WarningAction 0

Set-MailMailbox $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0

}

}

 

Import-Csv "Recipients.csv" |

ForEach {

$Found = $False

$Recipient = $Null

Write-Host "Looking for: $($_.Email)" -ForegroundColor Cyan

$Recipient = Get-Recipient $_.Email -ErrorAction SilentlyContinue

If ($Recipient -eq $Null) {

Write-Host "`tRecipient not found, creating" -ForegroundColor Yellow

#Create new Contact

$FullName = $_.Preferred + " " + $_.LastName

New-MailContact -Name $FullName -DisplayName $FullName -ExternalEmailAddress $_.Email -FirstName $_.FirstName -LastName $_.LastName

$Recipient = Get-Recipient $_.Email

}

Else {

#Update Recipient

Write-Host `t"Found: $($Recipient.Name)" -ForegroundColor Green

}

UpdateRecipient $Recipient $_

}

About jasonsherry

I am a 20 year Exchange consultant and expert. I currently work for Commvault as a Solutions Specialist for Microsoft Infrastructure For more info see my resume at: http://jasonsherry.org
This entry was posted in Exchange, O365, Script, Technical and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s