From dd961cbf6e63999098ba7c309e3537e85076546e Mon Sep 17 00:00:00 2001 From: Corbin Date: Wed, 25 Feb 2026 11:50:24 -0500 Subject: [PATCH] Add Entra update script --- m365/Update-UserEntraContactInformation.ps1 | 102 ++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 m365/Update-UserEntraContactInformation.ps1 diff --git a/m365/Update-UserEntraContactInformation.ps1 b/m365/Update-UserEntraContactInformation.ps1 new file mode 100644 index 0000000..ff1577d --- /dev/null +++ b/m365/Update-UserEntraContactInformation.ps1 @@ -0,0 +1,102 @@ +[CmdletBinding()] +param ( + [Parameter(Mandatory = $true)] + [string] + $Path, + [Parameter()] + [guid] + $TenantId, + [Parameter()] + [switch] + $UpdateName +) + +#region Private helper functions + +<# +.SYNOPSIS + Formats a phone number +.DESCRIPTION + Formats a phone number into the format (123) 456-7890 Ext. 1234 + + Takes a 15-digit E.164 phone number +.PARAMETER PhoneNumber + The phone number to format +#> +function Format-PhoneNumber { + [CmdletBinding()] + param ( + # The phone number to format + [Parameter(Mandatory=$true,ValueFromPipeline)] + [string] + $PhoneNumber + ) + + $Parts = [regex]::Matches($PhoneNumber, '^(\+\d{1,2})?[\s-]?\(?(\d{3})\)?[\s.-]?(\d{3})[\s.-]?(\d{4})(?:\s[E|e]?xt?\.?\s(\d+))?').Groups + + if ($Parts[5].Success) { + return "($($Parts[2])) $($Parts[3])-$($Parts[4]) Ext. $($Parts[5])" + } else { + return "($($Parts[2])) $($Parts[3])-$($Parts[4])" + } +} + +#endregion + +# Connnect to Microsoft Graph for the given tenant +if ($null -eq (Get-MgContext)) { + if ($null -eq $TenantId) { + Write-Warning "No tenant ID provided. Connecting to Microsoft Graph without tenant context." + Connect-MgGraph -NoWelcome -Scopes User.ReadWrite.All, Organization.Read.All + } else { + Connect-MgGraph -NoWelcome -Scopes User.ReadWrite.All, Organization.Read.All -TenantId $TenantId + } +} else { + Write-Verbose "Already connected to Microsoft Graph. Authenticated as $((Get-MgContext).Account) to tenant $((Get-MgContext).TenantId)." +} + +# Import the list of users +$Users = Import-Csv -Path $Path + +$Results = @() + +foreach ($User in $Users) { + Write-Progress -Activity "Updating user $($User.Email)" -Status "Processing $($Results.Count) of $($Users.Count)" -PercentComplete (($Results.Count / $Users.Count) * 100) + + # Try to match up the email address of the user with a Graph user. + # If it matches, return the UserId for use in later update step. + try { + $UserId = (Get-MgUser -Filter "Mail eq '$($User.Email)'").Id + } catch { + Write-Warning "User with email $($User.Email) not found in Microsoft Graph. Skipping update for this user. Error: $_" + Continue + } + + # Default properties + $NewProperties = @{} + + if ($UpdateName) { + if ($null -ne $User.GivenName -and $User.GivenName -ne '') { $NewProperties.GivenName = $User.GivenName } else { Write-Verbose "No given name provided for $($User.Email). Skipping update for this property." } + if ($null -ne $User.Surname -and $User.Surname -ne '') { $NewProperties.Surname = $User.Surname } else { Write-Verbose "No surname provided for $($User.Email). Skipping update for this property." } + if ($null -ne $User.DisplayName -and $User.DisplayName -ne '') { $NewProperties.DisplayName = $User.DisplayName } else { Write-Verbose "No display name provided for $($User.Email). Skipping update for this property." } + } + + if ($null -ne $User.JobTitle -and $User.JobTitle -ne '') { $NewProperties.JobTitle = $User.JobTitle } else { Write-Verbose "No job title provided for $($User.Email). Skipping update for this property." } + if ($null -ne $User.Department -and $User.Department -ne '') { $NewProperties.Department = $User.Department } else { Write-Verbose "No department provided for $($User.Email). Skipping update for this property." } + if ($null -ne $User.OfficeLocation -and $User.OfficeLocation -ne '') { $NewProperties.OfficeLocation = $User.OfficeLocation } else { Write-Verbose "No office location provided for $($User.Email). Skipping update for this property." } + + # Format phone numbers + if ($null -ne $User.BusinessPhone -and $User.BusinessPhone -ne '') { $NewProperties.BusinessPhones = @(Format-PhoneNumber -PhoneNumber $User.BusinessPhone) } else { Write-Verbose "No business phone provided for $($User.Email). Skipping update for this property." } + if ($null -ne $User.MobilePhone -and $User.MobilePhone -ne '') { $NewProperties.MobilePhone = Format-PhoneNumber -PhoneNumber $User.MobilePhone } else { Write-Verbose "No mobile phone provided for $($User.Email). Skipping update for this property." } + if ($null -ne $User.FaxNumber -and $User.FaxNumber -ne '') { $NewProperties.FaxNumber = Format-PhoneNumber -PhoneNumber $User.FaxNumber } else { Write-Verbose "No fax number provided for $($User.Email). Skipping update for this property." } + + # Update Graph user Entra properties + Update-MgUser -UserId $UserId @NewProperties + + $NewProperties.Id = $UserId + + $Results += [PsCustomObject]$NewProperties +} + +# $Results | sort OfficeLocation,DisplayName | select Id,DisplayName,License,JobTitle,@{Label='BusinessPhone';Expression={$_.BusinessPhones[0]}},MobilePhone,FaxNumber,CompanyName,OfficeLocation | Out-GridView +$Results | Sort-Object OfficeLocation,DisplayName | Select-Object Id,DisplayName,License,JobTitle,@{Label='BusinessPhone';Expression={$_.BusinessPhones[0]}},MobilePhone,FaxNumber,CompanyName,OfficeLocation | Export-Csv -Path results.csv -NoTypeInformation \ No newline at end of file