Public/UserManagement/TeamsUserCallingSettings/Set-TeamsUserCallingSettings.ps1

# Module: TeamsFunctions
# Function: VoiceConfig
# Author: David Eberhardt
# Updated: 16-OCT-2022
# Status: BETA




function Set-TeamsUserCallingSettings {
  <#
  .SYNOPSIS
    Sets CallingSettings (except Call Group) for one or more Users
  .DESCRIPTION
    Switches user calling settings by applying or removing AlsoRingTarget, UnansweredTarget or ForwardingToCallTarget.
  .PARAMETER UserPrincipalName
    Required. UserPrincipalName (UPN) of the User to parse
  .PARAMETER SetToDoNothing
    Resets the IfUnanswered setting to DoNothing and disables any forwarding settings. Does not impact AlsoRing
  .PARAMETER SetToDefault
    If call is not answered in 20s, Redirect to Voicemail. Disables any forwarding settings. Does not impact AlsoRing
  .PARAMETER AlsoRingTarget
    Enables Simultaneous Ringing with the target specified. Disables forwarding.
    Does not impact UnansweredCallTarget if UnansweredCallTarget is not specified
    Allowed values are: 'NoOneElse' (disables AlsoRing), a UserPrincipalName, a Phone Number, MyDelegates or
    'CallGroup'. Using CallGroup requires a CallGroup being already set or provided with Parameters CallGroupTargets
  .PARAMETER UnansweredCallTarget
    Enables Forward to the target specified if not answered. Disables forwarding.
    Does not impact AlsoRingTarget if AlsoRingTarget is not specified
    Allowed values are: 'None' (disables redirection if unanswered), a UserPrincipalName, a Phone Number, MyDelegates or
    'CallGroup'. Using CallGroup requires a CallGroup being already set or provided with Parameters CallGroupTargets
  .PARAMETER ForwardingToCallTarget
    Enables Forwarding of Calls to the target specified. Disables AlsoRing and Redirect if Unanswered.
    This will disable the AlsoRingTarget and UnansweredCallTarget and forward the call immediately (if not set to 'None')
    Allowed values are: 'None' (disables forwarding), a UserPrincipalName, a Phone Number, MyDelegates or
    'CallGroup'. Using CallGroup requires a CallGroup being already set or provided with Parameters CallGroupTargets
  .PARAMETER Delay
    Optional. The time the call will ring the user before it is forwarded (10-60s in increments of 10)
  .PARAMETER GroupNotificationOverride
    Optional. This setting overrides any specific notification setting set for the user on any call group the user is a member of.
  .PARAMETER WriteErrorLog
    Optional. If Errors are encountered, writes log to C:\Temp
  .PARAMETER PassThru
    Optional. Displays object after applying settings
  .EXAMPLE
    Set-TeamsUserCallingSettings [-UserPrincipalName] John@domain.com -SetToDoNothing
 
    Sets Calling Settings for John to "if Unanswered: Do nothing". This is the standard setting. Does not impact AlsoRing.
  .EXAMPLE
    Set-TeamsUserCallingSettings [-UserPrincipalName] John@domain.com -SetToDefault -PassThru
 
    Sets Calling Settings for John to "if Unanswered: After 20s, forward to Voicemail". This is the default setting.
  .EXAMPLE
    "John@domain.com" | Set-TeamsUserCallingSettings -AlsoRingTarget Jane@domain.com -WriteErrorLog
 
    Sets Calling Settings for John to also ring Jane. This is simultaneously ringing a single target
  .EXAMPLE
    Set-TeamsUserCallingSettings Jane@domain.com -ForwardToTarget Jill@domain.com
 
    Sets Calling Settings for Jane to forward calls to Jill (immediately). This is call forwarding to a single target
  .EXAMPLE
    Set-TeamsUserCallingSettings Jill@domain.com -UnansweredCallTarget +15551234567 -Delay 20
 
    Sets Calling Settings for Jill to forward calls to the Phone Number +1 555 1234 567 if not answered after 20 seconds.
  .EXAMPLE
    Set-TeamsUserCallingSettings Jill@domain.com -UnansweredCallTarget MyDelegates -Delay 30
 
    Sets Calling Settings for Jill to forward calls to her Delegates if not answered after 30 seconds.
  .EXAMPLE
    Set-TeamsUserCallingSettings Jill@domain.com -UnansweredCallTarget Voicemail -Delay 40
 
    Sets Calling Settings for Jill to forward calls to her voicemail if not answered after 40 seconds.
  .EXAMPLE
    Set-TeamsUserCallingSettings Jill@domain.com -AlsoRingTarget CallGroup -Delay 50
 
    Sets Calling Settings for Jill to also ring the her defined Call Group. This Group must already be set up.
    Additionally, disables Forwarding if set and enables Unanswered CallTarget if set and sets the Unanswered delay to 50s,
    but does not set or change the UnansweredCallTarget.
    To set up the Call Group, please use Set-TeamsUserCallGroup.
  .EXAMPLE
    Set-TeamsUserCallingSettings Josh@domain.com -AlsoRingTarget NoOneElse
 
    Sets Calling Settings for Josh to disable simultaneous ring
  .EXAMPLE
    Set-TeamsUserCallingSettings Josh@domain.com -UnansweredCallTarget None
 
    Sets Calling Settings for Josh to disable call forwarding if not answered
  .EXAMPLE
    Set-TeamsUserCallingSettings Josh@domain.com -ForwardingToCallTarget None
 
    Sets Calling Settings for Josh to disable call forwarding
  .EXAMPLE
    Set-TeamsUserCallingSettings Jeff@domain.com -GroupNotificationOverride Banner
 
    Sets Calling Settings for Jeff to override all Call Group Notifications for Jeff with Banner
    This overrides settings made by other userss in their Call Group as Jeff does not want to be rang for Call Group Calls.
  .INPUTS
    System.String
  .OUTPUTS
    System.Void
    System.Object
  .NOTES
    Wrapper for Set-CsUserCallingSettings that applies or removes Call targets only.
    For Settings pertaining to Call Groups please call Set-TeamsUserCallGroup.
  .COMPONENT
    VoiceConfiguration
  .FUNCTIONALITY
    Applies User Calling Settings behaviour and sets up or removes Call Targets
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Set-TeamsUserCallingSettings.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_VoiceConfiguration.md
  .LINK
    https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/
  #>


  [CmdletBinding( SupportsShouldProcess, DefaultParameterSetName = 'Setting', PositionalBinding = $false )]
  [Alias('Set-TeamsUCS')]
  [OutputType([PSCustomObject])]
  param(
    [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
    [Alias('ObjectId', 'Identity', 'SipUri')]
    [ValidateScript( {
        If ($_ -match '@') { $True } else {
          throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid UPN'
        } })]
    [string[]]$UserPrincipalName,

    [Parameter(Mandatory, ParameterSetName = 'SetToDoNothing', HelpMessage = "Sets IfUnanswered to 'Do Nothing'")]
    [switch]$SetToDoNothing,

    [Parameter(Mandatory, ParameterSetName = 'SetToDefault', HelpMessage = "Sets IfUnanswered to 'Voicemail'")]
    [switch]$SetToDefault,

    [Parameter(Mandatory, ParameterSetName = 'AlsoRing', HelpMessage = 'Call Target to also ring')]
    [Parameter(ParameterSetName = 'Unanswered', HelpMessage = 'Call Target to also ring')]
    [ValidateScript( {
        If ( $_ -eq 'NoOneElse' -or $_ -eq 'CallGroup' -or $_ -eq 'MyDelegates' -or $_ -match '@' -or `
            $_ -match '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|([0-9][-\s]?){4,20})((x|;ext=)([0-9]{3,8}))?$' ) { $True } else {
          throw [System.Management.Automation.ValidationMetadataException] "Value must be 'NoOneElse, 'CallGroup', a UPN or a valid phone number. E.164 format expected, min 4 digits, but multiple formats accepted. Extensions will be stripped"
        } })]
    [ArgumentCompleter( { @('NoOneElse', 'CallGroup', 'MyDelegates', '<UserPrincipalName>', '<PhoneNumber: tel:+...>') } )]
    [Alias('AlsoRingCallTarget')]
    [string]$AlsoRingTarget,

    [Parameter(Mandatory, ParameterSetName = 'Unanswered', HelpMessage = 'Call Target if unanswered in time')]
    [Parameter(ParameterSetName = 'AlsoRing', HelpMessage = 'Call Target if unanswered in time')]
    [ValidateScript( {
        If ( $_ -eq 'None' -or $_ -eq 'CallGroup' -or $_ -eq 'MyDelegates' -or $_ -eq 'Voicemail' -or $_ -match '@' -or `
            $_ -match '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|([0-9][-\s]?){4,20})((x|;ext=)([0-9]{3,8}))?$' ) { $True } else {
          throw [System.Management.Automation.ValidationMetadataException] "Value must be 'None', 'Voicemail', 'CallGroup', a UPN or a valid phone number. E.164 format expected, min 4 digits, but multiple formats accepted. Extensions will be stripped"
        } })]
    [ArgumentCompleter( { @('None', 'CallGroup', 'MyDelegates', 'Voicemail', '<UserPrincipalName>', '<PhoneNumber: tel:+...>') } )]
    [Alias('UnansweredTarget')]
    [string]$UnansweredCallTarget,

    [Parameter(Mandatory, ParameterSetName = 'Forward', HelpMessage = 'Call Target to forward calls to')]
    [ValidateScript( {
        If ( $_ -eq 'None' -or $_ -eq 'CallGroup' -or $_ -eq 'MyDelegates' -or $_ -eq 'Voicemail' -or $_ -match '@' -or `
            $_ -match '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|([0-9][-\s]?){4,20})((x|;ext=)([0-9]{3,8}))?$' ) { $True } else {
          throw [System.Management.Automation.ValidationMetadataException] "Value must be 'None', 'Voicemail', 'CallGroup', a UPN or a valid phone number. E.164 format expected, min 4 digits, but multiple formats accepted. Extensions will be stripped"
        } })]
    [ArgumentCompleter( { @('None', 'CallGroup', 'MyDelegates', 'Voicemail', '<UserPrincipalName>', '<PhoneNumber: tel:+...>') } )]
    [Alias('ForwardingTarget')]
    [string]$ForwardingToCallTarget,

    [Parameter(ParameterSetName = 'Unanswered', HelpMessage = 'Delay before invoking Call Settings')]
    [Parameter(ParameterSetName = 'SetToDefault', HelpMessage = 'Delay before invoking Call Settings')]
    [ValidateSet( 10, 20, 30, 40, 50, 60 )]
    [int]$Delay,

    [Parameter(ParameterSetName = 'Setting', HelpMessage = 'NotificationSetting Override for all Call Groups this user is a member in')]
    [ValidateSet('Ring', 'Mute', 'Banner')]
    [Alias('NotificationOverride')]
    [string]$GroupNotificationOverride,

    [Parameter(HelpMessage = 'No output is written by default, Switch PassThru will return changed object')]
    [switch]$PassThru,

    [Parameter(HelpMessage = 'Writes a Log File of Errors to C:\Temp')]
    [switch]$WriteErrorLog

  ) #param

  begin {
    Show-FunctionStatus -Level BETA
    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' }

    # Adding Types
    Add-Type -AssemblyName Microsoft.Open.AzureAD16.Graph.Client
    Add-Type -AssemblyName Microsoft.Open.Azure.AD.CommonLibrary

  } #begin

  process {
    Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)"
    foreach ($User in $UserPrincipalName) {
      #region Querying Identity
      $UserCallingSettings = $null
      try {
        $UserCallingSettings = Get-CsUserCallingSettings -Identity $User -ErrorAction Stop
      }
      catch {
        if ( $_.Exception.Message.Contains('Could not resolve user') -or $_.Errordetails.Message.Contains('was not found') ) {
          $ErrorMessage = "'$User' - User not found"
          Write-Verbose $ErrorMessage
        }
        else {
          $ErrorMessage = "'$User' - Error: $($_.Errordetails.Message)"
          Write-Error -Message $ErrorMessage
        }
        if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorMessage -Artifact "$User" }
        continue
      }
      #endregion

      #region SETTINGS
      #region ParameterSet SetToDoNothing and SetToDefault
      switch ( $PSCmdlet.ParameterSetName ) {
        'SetToDoNothing' {
          Write-Verbose -Message "User '$User' - Processing SetToDoNothing"
          if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to reset settings for '$User'", "$User", 'Set-CsUserCallingSettings')) {
            try {
              Write-Verbose -Message "User '$User' - Disabling IsForwardingEnabled"
              $null = Set-CsUserCallingSettings -Identity "$User" -IsForwardingEnabled $false -ErrorAction Stop
              Write-Information "INFO: User '$User' - Forwarding disabled"

              Write-Verbose -Message "User '$User' - Disabling IsUnansweredEnabled"
              $null = Set-CsUserCallingSettings -Identity "$User" -IsUnansweredEnabled $false -ErrorAction Stop
              Write-Information "INFO: User '$User' - Unanswered disabled"
            }
            catch {
              $ErrorLog = $_
              Write-Error -Message $ErrorLog
              if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
            }
          }
        }

        'SetToDefault' {
          Write-Verbose -Message "User '$User' - Processing SetToDefault"
          if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to apply default settings for '$User'", "$User", 'Set-CsUserCallingSettings')) {
            try {
              Write-Verbose -Message "User '$User' - Disabling Forwarding"
              $null = Set-CsUserCallingSettings -Identity "$User" -IsForwardingEnabled $false -ErrorAction Stop
              Write-Information "INFO: User '$User' - SetToDefault - Forwarding disabled"

              $UnansweredDelay = if ( $PSBoundParameters.ContainsKey('Delay') ) { '00:00:' + $Delay } else { '00:00:20' }
              $CsUserCallingSettings = @{
                IsUnansweredEnabled  = $true
                UnansweredTargetType = 'Voicemail'
                UnansweredDelay      = $UnansweredDelay
                ErrorAction          = 'Stop'
              }
              $null = Set-CsUserCallingSettings -Identity "$User" @CsUserCallingSettings
              Write-Information "INFO: User '$User' - SetToDefault - Forward to Voicemail after 20s if Unanswered"
            }
            catch {
              $ErrorLog = $_
              Write-Error -Message $ErrorLog
              if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
            }
          }
        }
      }
      #endregion

      #region ParameterSet AlsoRing and Unanswered
      if ( $PSCmdlet.ParameterSetName -eq 'AlsoRing' -or $PSCmdlet.ParameterSetName -eq 'Unanswered' ) {
        if ( $CsUserCallingSettings.ForwardingType -eq 'Immediate' ) {
          # Disabling Forwarding if enabled
          if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to disable Forwarding for '$User'", "$User", 'Set-CsUserCallingSettings')) {
            try {
              $CsUserCallingSettings = @{
                IsForwardingEnabled = $false
                ErrorAction         = 'Stop'
              }
              $null = Set-CsUserCallingSettings -Identity "$User" @CsUserCallingSettings
              Write-Information "INFO: User '$User' - Forwarding disabled"
            }
            catch {
              $ErrorLog = $_
              Write-Error -Message $ErrorLog
              if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
            }
          }
        }
      }

      # Processing AlsoRing and Unanswered as either can be present
      #region AlsoRingTarget
      if ( $PSBoundParameters.ContainsKey('AlsoRingTarget') ) {
        Write-Verbose -Message "User '$User' - Processing AlsoRingTarget"
        $CsUserCallingSettings = @{
          ErrorAction = 'Stop'
        }
        #region Preparing Options for provided AlsoRingTarget
        if ( $AlsoRingTarget -eq 'NoOneElse' ) {
          if ( $CsUserCallingSettings.ForwardingType -eq 'Simultaneous' ) {
            $CsUserCallingSettings += @{
              IsForwardingEnabled = $false
            }
            $ForwardingMessage = 'AlsoRing disabled'
          }
          else {
            $CsUserCallingSettings = $null
          }
        }
        elseif ( $AlsoRingTarget -eq 'CallGroup' ) {
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Simultaneous'
            ForwardingTargetType = 'Group'
          }
          $AlsoRingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType)"
        }
        elseif ( $AlsoRingTarget -eq 'MyDelegates' ) {
          if ( $UserCallingSettings.Delegates.Count -eq 0 ) {
            $CsUserCallingSettings = $null
            $ErrorLog = "User '$User' - AlsoRingTarget: MyDelegates - No delegates defined"
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
          else {
            $CsUserCallingSettings += @{
              IsForwardingEnabled  = $true
              ForwardingType       = 'Simultaneous'
              ForwardingTargetType = 'MyDelegates'
            }
            $AlsoRingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType)"
          }
        }
        elseif ( $AlsoRingTarget -match '@') {
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Simultaneous'
            ForwardingTargetType = 'SingleTarget'
            ForwardingTarget     = "$AlsoRingTarget"
          }
          $AlsoRingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType) $($CsUserCallingSettings.ForwardingTarget)"
        }
        elseif ( $AlsoRingTarget -match '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|([0-9][-\s]?){4,20})((x|;ext=)([0-9]{3,8}))?$') {
          $ForwardingTarget = $AlsoRingTarget | Format-StringForUse -As LineURI
          Write-Verbose -Message "User '$User' - ForwardingTarget normalised to '$ForwardingTarget'"
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Simultaneous'
            ForwardingTargetType = 'SingleTarget'
            ForwardingTarget     = "$ForwardingTarget"
          }
          $AlsoRingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType) $($CsUserCallingSettings.ForwardingTarget)"
        }
        else {
          # Setting object to $null to avoid applying erroneous settings
          $CsUserCallingSettings = $null
        }
        #endregion

        # Applying settings
        if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to set Simultaneous Ring for '$User'", "$User", 'Set-CsUserCallingSettings')) {
          try {
            if ( $CsUserCallingSettings ) {
              $null = Set-CsUserCallingSettings -Identity "$User" @CsUserCallingSettings
              Write-Information "INFO: User '$User' - $AlsoRingMessage"
            }
            else {
              Write-Verbose -Message "User '$User' - No Forwarding settings to apply/change!" -Verbose
            }
          }
          catch {
            $ErrorLog = $_
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
        }
      }
      #endregion

      #region UnansweredCallTarget
      if ( $PSBoundParameters.ContainsKey('UnansweredCallTarget') ) {
        Write-Verbose -Message "User '$User' - Processing UnansweredCallTarget"
        $CsUserCallingSettings = @{
          ErrorAction = 'Stop'
        }
        #region Preparing Options for provided UnansweredCallTarget
        if ( $UnansweredCallTarget -eq 'None' ) {
          $CsUserCallingSettings += @{
            IsUnansweredEnabled = $false
          }
          $UnansweredMessage = 'Do Nothing'
        }
        elseif ( $UnansweredCallTarget -eq 'CallGroup' ) {
          $CsUserCallingSettings += @{
            IsUnansweredEnabled  = $true
            UnansweredTargetType = 'Group'
          }
          $UnansweredMessage = "$($CsUserCallingSettings.UnansweredTargetType)"
        }
        elseif ( $UnansweredCallTarget -eq 'MyDelegates' ) {
          if ( $UserCallingSettings.Delegates.Count -eq 0 ) {
            $CsUserCallingSettings = $null
            $ErrorLog = "User '$User' - UnansweredCallTarget: MyDelegates - No delegates defined"
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
          else {
            $CsUserCallingSettings += @{
              IsUnansweredEnabled  = $true
              UnansweredTargetType = 'MyDelegates'
            }
            $UnansweredMessage = "$($CsUserCallingSettings.UnansweredTargetType)"
          }
        }
        elseif ( $UnansweredCallTarget -eq 'Voicemail' ) {
          $CsUserCallingSettings += @{
            IsUnansweredEnabled  = $true
            UnansweredTargetType = 'Voicemail'
          }
          $UnansweredMessage = "$($CsUserCallingSettings.UnansweredTargetType)"
        }
        elseif ( $UnansweredCallTarget -match '@') {
          $CsUserCallingSettings += @{
            IsUnansweredEnabled  = $true
            UnansweredTargetType = 'SingleTarget'
            UnansweredTarget     = "$UnansweredCallTarget"
          }
          $UnansweredMessage = "$($CsUserCallingSettings.UnansweredTargetType): $($CsUserCallingSettings.UnansweredTarget)"
        }
        elseif ( $UnansweredCallTarget -match '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|([0-9][-\s]?){4,20})((x|;ext=)([0-9]{3,8}))?$') {
          $UnansweredTarget = $UnansweredCallTarget | Format-StringForUse -As LineURI
          Write-Verbose -Message "User '$User' - UnansweredTarget normalised to '$UnansweredTarget'"
          $CsUserCallingSettings += @{
            IsUnansweredEnabled  = $true
            UnansweredTargetType = 'SingleTarget'
            UnansweredTarget     = "$UnansweredTarget"
          }
          $UnansweredMessage = "$($CsUserCallingSettings.UnansweredTargetType): $($CsUserCallingSettings.UnansweredTarget)"
        }
        else {
          # Setting object to $null to avoid applying erroneous settings
          $CsUserCallingSettings = $null
        }
        #endregion

        # Applying settings
        if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to enable IfUnanswered for '$User'", "$User", 'Set-CsUserCallingSettings')) {
          try {
            if ( $CsUserCallingSettings ) {
              if ( $PSBoundParameters.ContainsKey('Delay') ) {
                $CsUserCallingSettings += @{ UnansweredDelay = $('00:00:' + $Delay) }
                Write-Verbose -Message "User '$User' - UnansweredDelay - Setting delay to $($CsUserCallingSettings.UnansweredDelay)"
              }
              if ( -not $CsUserCallingSettings.Containskey('UnansweredDelay') ) {
                if ( $null -eq $UserCallingSettings.UnansweredDelay ) {
                  $CsUserCallingSettings += @{ UnansweredDelay = 00:00:20 }
                  Write-Verbose -Message "User '$User' - UnansweredDelay - Setting not provided and not found set on the User - using default ($($UserCallingSettings.UnansweredDelay))"
                }
                else {
                  $CsUserCallingSettings += @{ UnansweredDelay = $($UserCallingSettings.UnansweredDelay) }
                  Write-Verbose -Message "User '$User' - UnansweredDelay - Setting not changed: $($UserCallingSettings.UnansweredDelay)"
                }
              }
              $UnansweredMessage = $UnansweredMessage + " to forward after $($CsUserCallingSettings.UnansweredDelay)"
              $null = Set-CsUserCallingSettings -Identity "$User" @CsUserCallingSettings
              Write-Information "INFO: User '$User' - UnansweredCallTarget set to $UnansweredMessage"
            }
            else {
              Write-Verbose -Message "User '$User' - No Forwarding settings match!" -Verbose
            }
          }
          catch {
            $ErrorLog = $_
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
        }
      }
      #endregion
      #endregion

      #region ParameterSet Forward
      if ( $PSCmdlet.ParameterSetName -eq 'Forward' ) {
        $CsUserCallingSettings = @{
          ErrorAction = 'Stop'
        }
        #region Preparing Options for provided ForwardingToCallTarget
        if ( $ForwardingToCallTarget -eq 'None' ) {
          if ( $CsUserCallingSettings.ForwardingType -eq 'Immediate' ) {
            $CsUserCallingSettings += @{
              IsForwardingEnabled = $false
            }
            $ForwardingMessage = 'Forwarding disabled'
          }
          else {
            $CsUserCallingSettings = $null
          }
        }
        elseif ( $ForwardingToCallTarget -eq 'CallGroup' ) {
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Immediate'
            ForwardingTargetType = 'Group'
          }
          $ForwardingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType)"
        }
        elseif ( $ForwardingToCallTarget -eq 'MyDelegates' ) {
          if ( $UserCallingSettings.Delegates.Count -eq 0 ) {
            $CsUserCallingSettings = $null
            $ErrorLog = "User '$User' - ForwardingToCallTarget: MyDelegates - No delegates defined"
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
          else {
            $CsUserCallingSettings += @{
              IsForwardingEnabled  = $true
              ForwardingType       = 'Immediate'
              ForwardingTargetType = 'MyDelegates'
            }
          }
          $ForwardingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType)"
        }
        elseif ( $ForwardingToCallTarget -eq 'Voicemail' ) {
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Immediate'
            ForwardingTargetType = 'Voicemail'
          }
          $ForwardingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType)"
        }
        elseif ( $ForwardingToCallTarget -match '@') {
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Immediate'
            ForwardingTargetType = 'SingleTarget'
            ForwardingTarget     = "$ForwardingToCallTarget"
          }
          $ForwardingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType) $($CsUserCallingSettings.ForwardingTarget)"
        }
        elseif ( $ForwardingToCallTarget -match '^(tel:\+|\+)?([0-9]?[-\s]?(\(?[0-9]{3}\)?)[-\s]?([0-9]{3}[-\s]?[0-9]{4})|([0-9][-\s]?){4,20})((x|;ext=)([0-9]{3,8}))?$') {
          $ForwardingTarget = $ForwardingToCallTarget | Format-StringForUse -As LineURI
          Write-Verbose -Message "User '$User' - ForwardingTarget normalised to '$ForwardingTarget'"
          $CsUserCallingSettings += @{
            IsForwardingEnabled  = $true
            ForwardingType       = 'Immediate'
            ForwardingTargetType = 'SingleTarget'
            ForwardingTarget     = "$ForwardingTarget"
          }
          $ForwardingMessage = "$($CsUserCallingSettings.ForwardingType) Forwarding enabled to $($CsUserCallingSettings.ForwardingTargetType) $($CsUserCallingSettings.ForwardingTarget)"
        }
        else {
          # Setting object to $null to avoid applying erroneous settings
          $CsUserCallingSettings = $null
        }
        #endregion

        # Applying settings
        if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to enable Forwarding for '$User'", "$User", 'Set-CsUserCallingSettings')) {
          try {
            if ( $CsUserCallingSettings ) {
              $null = Set-CsUserCallingSettings -Identity "$User" @CsUserCallingSettings
              Write-Information "INFO: User '$User' - $ForwardingMessage"
            }
            else {
              Write-Verbose -Message "User '$User' - No Forwarding settings to apply/change!" -Verbose
            }
          }
          catch {
            $ErrorLog = $_
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
        }
      }
      #endregion


      #region GroupNotificationOverride
      if ( $PSBoundParameters.ContainsKey('GroupNotificationOverride') ) {
        Write-Verbose -Message "User '$User' - Processing GroupNotificationOverride"
        if ($PSCmdlet.ShouldProcess("Calling 'Set-CsUserCallingSettings' to apply GroupNotificationOverride for '$User'", "$User", 'Set-CsUserCallingSettings')) {
          try {
            $CsUserCallingSettings = @{
              GroupNotificationOverride = $GroupNotificationOverride
              ErrorAction               = 'Stop'
            }
            $null = Set-CsUserCallingSettings -Identity "$User" @CsUserCallingSettings
            Write-Information "INFO: User '$User' - GroupNotificationOverride set to '$GroupNotificationOverride'"
          }
          catch {
            $ErrorLog = $_
            Write-Error -Message $ErrorLog
            if ( $WriteErrorLog.IsPresent ) { Write-TFErrorLog -ErrorLog $ErrorLog -Artifact "$User" }
          }
        }
      }
      #endregion
      #endregion


      # OUTPUT
      $OutputObject = $null
      if ( $PassThru ) {
        $OutputObject = Get-TeamsUserCallingSettings -UserPrincipalName $User
      }
      Write-Output $OutputObject
    }
  } #process

  end {
    Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)"
  } #end
} #Set-TeamsUserCallingSettings