Public/Support/VoiceConfig/Set-TeamsPhoneNumber.ps1
# Module: TeamsFunctions # Function: Teams User Voice Configuration # Author: David Eberhardt # Updated: 13-FEB-2022 # Status: Live #TODO For Later: When adding -Location, catch "Contact your operator to change the emergency address for this number." - OperatorConnect numbers cannot be assigned a location - display this error (warning?) instead? function Set-TeamsPhoneNumber { <# .SYNOPSIS Applies a Phone Number to a User Object or Resource Account .DESCRIPTION Applies a Microsoft Calling Plans Number OR a Direct Routing Number to a User or Resource Account .PARAMETER UserPrincipalName Required for Parameterset UserPrincipalName. UserPrincipalName of the Object to be assigned the PhoneNumber. This can be a UPN of a User Account (CsOnlineUser Object) or a Resource Account (CsOnlineApplicationInstance Object) .PARAMETER Object Required for Parameterset Object. CsOnlineUser Object passed to the function to reduce query time. This can be a UPN of a User Account (CsOnlineUser Object) or a Resource Account (CsOnlineApplicationInstance Object) .PARAMETER PhoneNumber A Microsoft Calling Plans Number or a Direct Routing Number Requires the Account to be licensed. Able to enable PhoneSystem and the Account for Enterprise Voice Required format is E.164 or LineUri, starting with a '+' and 10-15 digits long. .PARAMETER Force Suppresses confirmation prompt unless -Confirm is used explicitly Scavenges Phone Number from all accounts the PhoneNumber is currently assigned to including the current User .EXAMPLE Set-TeamsPhoneNumber -UserPrincipalName John@domain.com -PhoneNumber +15551234567 Applies the Phone Number +1 (555) 1234-567 to the Account John@domain.com .INPUTS System.String .OUTPUTS System.Void - If called directly Boolean - If called by another CmdLet .NOTES Simple helper function to assign a Phone Number to any User or Resource Account Returns boolean result and less communication if called by another function Can be used providing either the UserPrincipalName or the already queried CsOnlineUser Object .COMPONENT VoiceConfiguration .FUNCTIONALITY Enables a User for Enterprise Voice in order to apply a valid Voice Configuration .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Set-TeamsPhoneNumber.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_VoiceConfiguration.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_UserManagement.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_Supporting_Functions.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/ #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'UserPrincipalName')] [OutputType([Boolean])] param( #TEST Whether both Object and Identity work - replicate for Set-TeamsCAP [Parameter(Mandatory, Position = 0, ParameterSetName = 'Object', ValueFromPipeline)] [Object[]]$Object, [Parameter(Mandatory, Position = 0, ParameterSetName = 'UserPrincipalName', ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('ObjectId', 'Identity')] [ValidateScript( { If ($_ -match '@' -or $_ -match $script:TFMatchGuid) { $True } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid UPN or ObjectId' } })] [string[]]$UserPrincipalName, [Parameter(Mandatory, Position = 1, HelpMessage = 'Telephone Number to assign')] [AllowNull()] [AllowEmptyString()] [Alias('Tel', 'Number', 'TelephoneNumber')] [string]$PhoneNumber, [Parameter(HelpMessage = 'Suppresses confirmation prompt unless -Confirm is used explicitly')] [switch]$Force ) #param begin { Show-FunctionStatus -Level Live Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # Asserting MicrosoftTeams Connection if ( -not (Assert-MicrosoftTeamsConnection) ) { break } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' } if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' } if ( $PSBoundParameters.ContainsKey('ErrorAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ErrorAction') } else { $ErrorActionPreference = 'Stop' } $Stack = Get-PSCallStack $Called = ($stack.length -ge 3) if ( -not $global:TeamsFunctionsMSTeamsModule) { $global:TeamsFunctionsMSTeamsModule = Get-Module MicrosoftTeams } if ( [String]::IsNullOrEmpty($PhoneNumber) ) { $PhoneNumber = $null } else { If ($PhoneNumber -notmatch '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|[0-9]{8,15})((;ext=)([0-9]{3,8}))?$') { throw [System.Management.Automation.ValidationMetadataException] 'Not a valid phone number. Must be 8 to 15 digits long' } } # Preparing Splatting Object $parameters = $null $Parameters = @{ 'PhoneNumber' = $PhoneNumber 'Called' = $Called 'Force' = $Force 'ErrorAction' = 'Stop' } #endregion } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" try { switch ($PSCmdlet.ParameterSetName) { 'UserprincipalName' { foreach ($User in $UserPrincipalName) { Write-Verbose -Message "[PROCESS] Processing provided UserPrincipalName '$User'" try { $CsUser = Get-CsOnlineUser -Identity "$User" -WarningAction SilentlyContinue -ErrorAction Stop $UserLicense = Get-AzureAdUserLicense "$User" } catch { Write-Error "'$User' not found" -Category ObjectNotFound continue } if ($Force -or $PSCmdlet.ShouldProcess("$($CsUser.UserPrincipalName)", 'Set Phone Number')) { Set-TFPhoneNumber -UserObject $CsUser -UserLicense $UserLicense @Parameters } } } 'Object' { foreach ($O in $Object) { Write-Verbose -Message "[PROCESS] Processing provided CsOnlineUser Object for '$($O.UserPrincipalName)'" $UserLicense = Get-AzureAdUserLicense "$($O.UserPrincipalName)" if ($Force -or $PSCmdlet.ShouldProcess("$($CsUser.UserPrincipalName)", 'Set Phone Number')) { Set-TFPhoneNumber -UserObject $O -UserLicense $UserLicense @Parameters } } } } } catch { Write-Error -Message $($_.Exception.Message) -ErrorAction $ErrorActionPreference } } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Set-TeamsPhoneNumber |