Have you ever had the need to redirect inbound phone calls to Lync to another destination, maybe even residing outside of Lync? If so; have you ever struggled getting it working?
Either case, this post may be of interest to you; to understand why, how and what to look for if it isn’t working.
There may be several reasons for redirecting or forwarding a call.
- In a recent customer case I had to redirect a branch office’s main number to the central site switchboard, still residing on the legacy PBX system, during coexistence
- A colleague used it to redirect the fax number to an internet fax service provider (as Lync fax support is not the best)
- Published number is no longer assigned to a user, but needs to be handled by the organisation
In Lync phone numbers are not separate entities like the case is with other PBX systems, such as in Cisco UCM. A phone number only exists whenever assigned to a user or endpoint, so how would you go about redirecting it?
So now that we have some use cases for redirecting or forwarding the calls, lets look into how to achieve this.
Technically there are several ways this could be done:
- Creating a dummy user account and assigning it the number in question, then using SEFAUtil forwarding all calls. Although it sounds like a simple solution, it is both impractical as well as requiring additional licenses (at least from Microsoft’s point of view)
- Creating a dummy Agent Group, Queue and Response Group that will handle incoming calls to the number assigned to the Response Group. The RGS object can in turn be set up to forward all calls. Although no additional licenses are required with this solution, it is still an impractical solution requiring several “dummy” objects not really doing anything.
- Using an Unassigned Number Range along with an Announcement Service, which is capable of doing Call Forwarding as well as prompting the caller through a sound file or Text-To-Speech.
The third one is the preferred option, and the one I will focus on.This solution takes two steps to complete; first you need to create an Announcement, which is the prompt and the action that will be taken for the call handed over to it, then you will need to create an Unassigned Number range that will “catch” the number (range) in question.
Creating an Announcement can only be achieved from the Lync Server Management Shell, using Powershell commandlets.
New-CsAnnouncement commandlet takes four main inputs:
- The name of your announcement, such as “Unassigned number”
- The Identity of your Application server. This is your Front End Pool.
- The voice announcement you would like to have. This can either be a previously uploaded voice prompt or using Text-To-Speech (TTS), in which case you will also need to add the -Language parameter. Or, it could also be left blank.
- The forwarding destination, which can be a SIP URI or a phone number. This can also be left blank if you simply want to terminate the call.
So, lets say you want an announcement for anyone who calls a number within your organisation that does not belong to a user, and to have that call transferred to your switchboard:
New-CsAnnouncement -Name "Unassigned number" -Identity ApplicationServer:your.pool.fqdn -TextToSpeechPrompt "You have reached an unassigned number. Your call will be forwarded to the switchboard" -Language "en-US" -TargetUri "sip:firstname.lastname@example.org"
If you’d rather have the call forwarded to a phone number, simply change the TargetUri value to
"sip:<E.164number>@yourdomain.com;user=phone". The third alternative is to forward to a user’s voice mail, where you simply append
"opaque=app:voicemail" to the users SIP address, e.g.:
"sip:email@example.com;opaque=app:voicemail" in the TargetUri field.
Once you have your announcement ready move on to defining the Unassigned Number Range, which can be as the name indicates a whole range of numbers (even including those in use by your organisation) or just a single one. This operation can be done both through Control Panel or PowerShell. The first one needs little or no explanation, and since we’re already doing things in Lync Management Shell, let’s continue doing that.
New-CsUnassignedNumber takes five inputs, all mandatory:
- The Identity of your range. Simply a tag making it unique.
- The Starting Number in the Range.
- The Ending Number in the Range. If just a single number is what you want, simply make this the same as the previous.
- The Identity of your Announcement service. Basically the same as the -Identity parameter under New-CsAnnouncement.
- The name of the specific Announcement you want to assign.
New-CsUnAssignedNumber -Identity "Undef1" -NumberRangeStart "tel:<E.164number>" -NumberRangeEnd "tel:<E.164number> -AnnouncementService ApplicationServer:your.pool.fqdn -Announcement "Unassigned number"
An alternative to using the previous announcement is utilizing an Exhange UM Auto Attendant, provided you have one set up. In that case, simply replace the AnnouncementService and Announcement parameters With
-ExUmAutoAttendantPhoneNumber and the number for it.
The Lync server will run a Reverse Number Lookup on all calls, trying to match it with a user homed in it’s pool. If no match is found then it will continue looking at Unassigned Number ranges, and if the called number should fall within such a range, then the call will be handled according to the Announcement or EXUM AA parameter.
Now that wasn’t too hard, was it?
The What (The F…)
First a little something to remember: If you insist on using Lync Server Control Panel whenever possible, just make sure you create the Announcement before you even open LSCP. It has this thing of caching stuff from when it starts up, so that a freshly defined Announcement might not show up in LSCP during Unassigned Number setup, and you have to exit and reopen LSCP.
So, having set up Announcement and Unassigned Number range you might, as I did, realise that it does not work. Like I mentioned initially, my goal was to forward the call off Lync’s territory and onto a PBX system. Incoming calls to my single number “range” got the TTS prompt, but then simply disconnected. At this point I tried altering the Announcement, trying a SIP address instead of a phone number – and found it to be working. This is where you have narrowed the problem down to a Routing or Authorization issue.
The first thing to look for is whether Call Forwarding is working at all, that is; for your regular users. Although enabled by default, call forwarding can be disabled through policy. Also, settings regarding SIP Refer support on the trunk can lead to problems related to forwarding since it has to do with call handling between the connected systems. Check with your service provider or the one responsible for any PBX you are connecting to if you are uncertain of what the settings should be like. In my case, my Lync account was able to transfer and forward calls off of Lync, and Refer settings on the trunk were correct as well.
Continuing troubleshooting you have to dig into some logging. As this is a call related issue, using the IncomingAndOutgoingCall scenario With Centralized Logging Service (CLS) will provide that kind of information:
Start-CsClsLogging -Scenario IncomingAndOutgoingCall -pools Your.mediationpool.fqdn
After having completed some test calls, simply run the above command, replacing
To output info from your logging session (by now in .etl format) you will have to run something like:
Search-CsClsLogging -pools Your.mediationpool.fqdn -OutputFilePath "C:\temp\AnnouncementFail.txt" (of course, you can name the file and path anything)
Search- cmdlet takes parameters for
EndTime, and in a large organisation it might be useful to limit the scope this way – by default it will output the last half hour or so, and that might give you a really large file to parse through. Although it is possible to filter by
Phone (number) and
URI, I often leave those out and rather do the filtering when parsing the file in Snooper.
When I started parsing through the text file, filtering by the phone number used as TargetUri, I found this error related to the failed outbound Routing of my Announcement:
TL_ERROR(TF_PROTOCOL) [pool\lyncfe1]1608.4830::08/21/2013-10:17:11.447.0000122F (MediationServer,ProxyCall.FinishParticipate:proxycall.cs(3314)) 33083874FailureResponseException: ResponseCode=403 ResponseText=Forbidden
DiagnosticInformation=ErrorCode=12001,Source=LYNCFE1.YOURDOMAIN.COM,Reason=User Policy does not contain phone route usage,appname=OutboundRouting,useruri=sip:RtcApplicationfirstname.lastname@example.org
From the error message, the cause is really clear about why it is not working. I have highlighted the relevant parts, stating the SIP 403 response along With the more verbose “Reason” field. It seemed like the user policy did not offer a “phone route usage”.
Now two Things needs to be cleared out:
- What is a “phone route usage”?
- What user and policy is this referring to?
The first one, although listed as a single entity, refers to both PSTN Usage and Voice Route – two fundamental parts of Lync Enterprise Voice. In short, a Voice Route holds a number pattern that the destination number needs to fall within and if so which gateway the call will go to. The PSTN Usage will simply tie one or more routes to the Voice Policy of the user in question.
So, to the next question, what user is this referring to? The answer is also given in the previous error message: useruri=sip:RtcApplicationemail@example.com.
This is not your regular user, but rather the endpoint assosciated With your Announcement service – automatically created by Lync and normally you would never have to relate to it, as it works silently under the hood. But since we now have problems related to this “user” (or endpoint) and it’s assosciated user policy, we need to dig a little more into this.
The Announcement service endpoint is addressed through the
CsApplicationEndpoint cmdlets, but the
Get- cmdlet will by default not output the info we are interested in, so you will have to something like this:
As you can tell by the output, there is no Voice Policy assigned to the endpoint. This is not uncommon, as it will automatically be assigned a Site or Global Voice policy if no User Scope policy is specifically designated. In most cases this will work just fine, as some administrators might want to use the Site or Global policies for their voice enabled users. In my case I wanted all users enabled for Voice to be explicitly assigned a policy stating what “calling permissions” the user had, and therefore the Global (no Site policy in my case) policy did not contain any PSTN Usages.
To solve this I could simply have changed the Global policy to include a PSTN Usage pointing to a valid Voice Route that would accept the number I was forwarding to. This would unfortunately also allow any user enabled for Enterprise Voice and not assigned a User Scope policy the right to call numbers they might not be authorized for.
So taking the more restrictive approach to this, I would rather assign (or “grant” as the PowerShell way states) the actual Announcement endpoint the necessary policy to be authorized for this call:
Get-CsApplicationEndpoint "sip:RtcApplicationfirstname.lastname@example.org" | Grant-CsVoicePolicy -PolicyName "User - Limited"
Now, let’s review the endpoint attributes once more:
As you can tell, the endpoint that handles the Announcement service now does contain a Voice policy (text in Norwegian, “Begrenset” translates to “Limited”) and should be able to do the same Things that a regular User having the same Policy.
A test call would now confirm that the Announcement works as intended. So to sum up, if you your Announcement or Forwarding is not working:
- Test whether changing the TargetUri to an internal SIP address makes a difference – it should.
- Test whether regular users can Forward their calls. If not, check the Voice Policy to see what PSTN Usage and Voice Route they are assigned
- If Call Forwarding still fails, check the SIP refer settings of your trunk – check with your Service Provider or interconnected PBX system admin to sort out the proper ones
- Once you have Call Forwarding working for regular users, assign the Announcement Service endpoint a Voice Policy you by now have confirmed operational