Wednesday, February 22, 2012

Re-routing Incoming Lync Calls to AutoAttendant Using MSPL Scripting

Many companies assign extensions to their users rather than dedicating a full external phone number.  In companies with thousands of users, this is often the only option, plus it can save significant amounts of money.  If you've followed my Enterprise Voice Best Practices for extensions, then you know that I recommend you assign phone numbers to Lync Enterprise Voice users using the main office number as the base followed by the extension, using the format tel:<OfficeNumberinE164Format>;ext=<Extension>.  For example, if your main office number is 15553334444, and your extension is 222, then your Tel URI would be tel:+15553334444;ext=222.  You then create a normalization rule that takes the main office number and routes it to an Exchange autoattendant at an unused extension, such as tel:+15553334444;ext=999.  When someone calls the main office number, the phone call will be routed to the Exchange autoattendant where they can enter the extension of the user they wish to reach.

This works fine in many deployments, but in situations where the incoming phone number is already formatted in E.164 format (as with many SIP providers), it breaks down.  When Lync sees a number that starts with a +, it assumes the number is normalized properly and does not apply normalization rules, no matter how hard you try.  Users get a busy signal and if you do a log trace, you'll see the error 485 Ambiguous.  Lync sees many users with the same base phone number, and doesn't know where to send the call.

In many of those cases, you can either set your PSTN gateway (if you are using one) to not send the + to Lync, or you can ask your SIP provider to drop the +.  If neither of those options are available, then you can employ MSPL scripting to re-route the incoming call to the appropriate autoattendant.

MSPL scripts are simple text-based programs that can do custom message routing and filtering in Lync.  They can be very powerful, if you know how to create them.  Now, having exactly zero experience with MSPL scripting, I turned to the only way I know how to program:  Google/Bing for examples.  Thanks to some excellent blog posts by Michael Greenlee (which made me hyperventilate because most of it was totally incomprehensible to me) and a terrific example by Lasse Wedø (where he did the bulk of the work for me), I was able to figure out how to make this work in my specific example.

First, copy the contents of the below window into Notepad on a server that is running the Mediation Server role.

Do a search-and-replace for and use your public domain name instead.

Then do another search-and-replace for 15552229999 and use your main office number instead.

Finally, do a search-and-replace for and replace it with the SIP URI of your Exchange autoattendant or response group.  You can determine the SIP URI by running the OcsUmUtil.exe program (located in C:\Program Files\Common Files\Microsoft Lync Server 2010\Support).  This program is used to create the necessary contact objects to connect Lync to Exchange UM.  Once you click Load Data, make note of the SIP URI for the appropriate AA, and do a search-and-replace for in the script using the information you found from OcsUmUtil.

Then save the script on your mediation server/front-end in a folder like C:\MSPLScripts, calling it  If you have multiple servers in the pool, copy the script to each server.

Now, open Lync Management Shell and type the following (make sure you replace with your public domain name):
New-CsServerApplication -Name ReroutePilotNumtoAA -Parent Service:Registrar:
<lyncpoolFQDN> -Uri -Enabled $TRUE -Critical $FALSE -ScriptName c:\MSPLScripts\ -Priority 2
If all goes well, you should see a few events in the Lync Server Event Viewer like the following:

Log Name:      Lync Server
Source:        LS Script-Only Applications
Event ID:      30803
Description: Loading application - 'c:\MSPLScripts\'

Log Name:      Lync Server
Source:        LS Applications Module
Event ID:      30208
Description: Lync Server application has successfully registered.
Application Uri ''
Open Lync Control Panel and go to Topology - Server Application and you should see the new script between TranslationService and UserServices.

If the script doesn't work you will see the error logged in the Event Viewer.  If so, click Action and Disable Application.  After a few minutes, you should see an event saying the script was disabled.  Make any necessary fixes and re-enable.  It will take a few minutes to restart.  Once you get a clean start, try calling the main office number.  You should be directed to the chosen Exchange autoattendant.

Every time the script runs, it will log a warning event saying that the number was forwarded to the autoattendant.  If you don't want to see this event, comment the line that starts with Log("Event" with a //.

What is happening behind the scenes is that the script is looking for an INVITE for the main office number.  If it sees that, it will respond to the system making the call with a 302 Moved Temporarily.  This tells the system to forward the call to the new destination.

I recommend that you thoroughly document the procedure for future Lync administrators.  If you hand off Lync administration to someone else, it will be very difficult to determine that a script is being used to re-route the office number.  It doesn't make itself known when doing a typical log trace.  If you make a call to the office number, the trace will only show the phone call is going to the AA.  It won't show the script making the forward.

Also, note that this procedure can be used to forward calls to ANY SIP URI, not just an Exchange autoattendant.  It can be an autoattendant, a response group or an individual user.

This is my first foray into MSPL scripting.  If you notice any errors, please let me know.

For more funtastic MSPL examples, check out VOIPNorm's blog.