Entra / Microsoft 365 · Exchange Online
Add contacts to mailboxes
Copies organizational contacts from a SharePoint list into Exchange user mailboxes for newly licensed users, using app-only Microsoft Graph permissions.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -NoWelcome -TenantId $TenantId -ClientId $AppId -CertificateThumbprint $CertThumbPrint
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([string] $TenantId = "",[string] $AppId = "",[string] $CertThumbPrint = "",[string] $SiteSearch = "Experts Team",[int] $LookbackDays = 7)# We need to use application permissions to add contacts to mailboxesConnect-MgGraph -NoWelcome -TenantId $TenantId -ClientId $AppId -CertificateThumbprint $CertThumbPrint# Define the service plan IDs for Exchange Online (Plan 1) and Exchange Online (Plan 2)$ExoServicePlan1 = "9aaf7827-d63c-4b61-89c3-182f06f82e5c"$ExoServicePlan2 = "efb87545-963c-4e0d-99df-69c6916d9eb0"# Define the check date to find new mailboxes$CheckDate = [datetime]::UtcNow.AddDays(-$LookbackDays).ToString("s") + "Z"# Find the organizational contacts to add$Site = Get-MgSite -Search $SiteSearchIf (!$Site) {Write-Host "Site not found"Break}$List = Get-MgSiteList -SiteId $Site.Id -Filter "displayName eq 'Organizational Contacts'"If (!$List) {Write-Host "List not found"Break}[array]$ListItems = Get-MgSiteListItem -ListId $List.Id -SiteId $Site.Id -PageSize 999 -All `-ExpandProperty "fields(`$select=id,title,fullname,firstname,workphone,email,workcity,description)"$ItemData = [System.Collections.Generic.List[Object]]::new()ForEach ($Item in $ListItems.fields) {$ReportLine = [PSCustomObject] @{Id = $Item.IdFullName = $Item.AdditionalProperties.FullNameFirstName = $Item.AdditionalProperties.FirstNameLastName = $Item.AdditionalProperties.TitlePhoneNumber = $Item.AdditionalProperties.WorkPhoneEmail = $Item.AdditionalProperties.EmailCity = $Item.AdditionalProperties.WorkCityDescription = $Item.AdditionalProperties.Description}$ItemData.Add($ReportLine)}Write-Host ("Found {0} organizational contacts to process" -f $ItemData.Count)# Find users assigned a license that includes the Exchange Online (Plan 1) or Exchange Online (Plan 2) service plans who were created# since the check date. The check also looks for users with the Exchange Online service plan enabled.[array]$Users = Get-MgUser -Filter "assignedPlans/any(c:c/servicePlanId eq $ExoServicePlan1 and capabilityStatus eq 'Enabled') `or assignedPlans/any(c:c/servicePlanId eq $ExoServicePlan2 and capabilityStatus eq 'Enabled') and (CreatedDateTime ge $CheckDate)" `-ConsistencyLevel eventual -CountVariable Test -All -PageSize 999 -Sort ('displayname') `-Property Id, displayName, userprincipalName, assignedLicenses, assignedPlans, department, country, CreatedDateTimeIf ($Users.count -eq 0) {Write-Host "No new mailboxes found to update with organizational contacts"Break} Else {Write-Host ("Found {0} new mailboxes to update with organizational contacts" -f $Users.Count)}[int]$ContactAdded = 0ForEach ($User in $Users) {Write-Host ("Processing user {0}" -f $User.displayName)# Get the existing contacts so that we can avoid adding duplicates[array]$Contacts = Get-MgUserContact -UserId $User.Id -All -PageSize 999 | Select-Object -ExpandProperty $EmailAddresses$ContactsHash = @{}ForEach ($Contact in $Contacts) {# Before adding, check that the contact has an email address and that it's not already in the hash$EmailAddress = $Contact.emailAddresses[0].addressIf ($EmailAddress -and $null -eq $ContactsHash[$EmailAddress]) {$ContactsHash.Add($EmailAddress,$Contact.displayName)}}ForEach ($Item in $ItemData) {$NewContactEmail = @{address = $Item.Emailname = $Item.FullName}$NewContactEmails = @($NewContactEmail)# Build body for new contact$NewContact = @{}$NewContact.Add("FileAs", $Item.FullName)$NewContact.Add("Surname", $Item.LastName)$NewContact.Add("GivenName", $Item.FirstName)$NewContact.Add("OfficeLocation", $Item.City)$NewContact.Add("PersonalNotes", $Item.Description)$NewContact.Add("emailAddresses", $NewContactEmails)$NewContact.Add("businessPhones", @($Item.PhoneNumber))$NewContact.Add("DisplayName", $Item.FullName)# Check if the contact already exists and add it if it's not thereIf ($null -eq $ContactsHash[$Item.Email]) {Write-Host ("Adding contact {0} to {1}" -f $Item.FullName, $User.displayName)Try {$Contact = New-MgUserContact -UserId $User.Id -BodyParameter $NewContact} Catch {Write-Host ("Failed to add contact {0} to {1}" -f $Item.FullName, $User.displayName)}If ($Contact) {$ContactAdded++}}}}Write-Host ("Added {0} contacts to {1} mailboxes" -f $ContactAdded, $Users.Count)
Parameters
ParameterDefaultNotes
-TenantId""Microsoft Entra tenant ID for app-only Graph authentication.-AppId""Application (client) ID for the app registration used to connect.-CertThumbPrint""Certificate thumbprint for app-only Graph authentication.-SiteSearchExperts TeamSharePoint site search term used to locate the organizational contacts list.-LookbackDays7How many days back to search for newly created mailboxes or recent activity.Attribution
Author
Office365itpros