**Contribution**: Unified Voicemail and Company Directory across multiple boxes
Introduction:
I wanted to start a fresh post regarding setting up a distributed, unified voicemail and company directory application. I have this setup working in a multi-server environment currently deployed between my offices. I'm sure there could be improvement (and any such improvement are welcomed), but this is what I have functioning now. This guide will cover the entire creation with the exception of Trunks. There are plenty of guides out there on trunking, this configuration should work with any trunk type that allows direct extension dialing between offices.
Getting Started:
Here are the assumptions I'm working under, you'll need to adjust these for your setup:
Local Extenstions: 1XX
Remote Extensions: 2XX
Main IVR labeled [ivr-2] (this will vary greatly, and is generated by FreePBX or PBXConfig
To get things going, you'll need to have one or more trunks configured for your PBX-to-PBX linking. Mine is called inter-office, call your's whatever you like.
1. Configure an outbound route to support the dialing rules of your trunk, here are my outbound dialing rules for my inter-office trunk (with comments next to them for clarity)
Intra-Company Route = Checked
Dial Patterns:
608 <-- This is a ring group on my remote box (you may or may not want this one)
*2XX <-- This allows for transferring calls directly to remote extensions voicemail
*802XX <-- This allows direct intercom dialing of remote extensions
*982XX <-- This entry is required for accessing remote mailboxes
2XX <-- These are my remote extensions
70X <-- This allows me to access the remote parking lot (700-709), local parking lot is (710-719)
Manually Editing your extensions_custom.conf file:
1. Put the following entry into extensions_custom.conf for your remote extensions:
[ext-local-custom]
exten => _2XX,1,goto(outbound-allroutes,${EXTEN},1) ;send call to outbound routes for trunking.
2. Find each IVR that you want to enable direct dial through to remote offices. Mine is labeled [ivr-2], so I need to add the following entry to extensions_custom.conf
[ivr-2-custom]
exten => _2XX,1,goto(outbound-allroutes,${EXTEN},1) ;send call to outbound routes for trunking.
Manually Editing Your voicemail.conf file:
Now, you need to edit the voicemail.conf file on each of your servers to contain entries from your other servers, the entries can contain bogus passwords, since they are only serving as directory place-holders. If you want to get really slick, you can copy their name file from their home server over to the foriegn server if you want the directory to be able to play the remote user's name back. Fortunately, the updates from FreePBX / PBXConfig are non-destructive in this file, so you won't lose your changes after every re-load.
Bringing it all together with extensions_override_freepbx.conf:
Here is the code that does the heavy lifting for call routing when a user dials *98 or *98XXX. This code will need to be updated in the event you don't want to use *98 for voicemail. This code needs to be placed in the extensions_override_freepbx.conf file. There will be modifications necessary to fit your dial-plan, but it's all noted in the module:
[app-dialvm]
;******************************************************************************
; Module written by Chris Vanderbles, using code from FreePBX, and help from *
; the trixbox community. This module is known to work with Asterisk 1.2 and *
; Asterisk 1.4. Functionality with 1.6 has not been determined 12-05-2008 *
; This module assumes that you have 2 or more asterisk boxes interconnected *
; via trunks with the context of from-internal SIP or IAX2 should work *
; equally well. *
;******************************************************************************
;******************************************************************************
; This sections catches *98 and simulates the standard app-dialvm application *
; but checks the extension input into the system and routes the call *
; accordingly. Outbound routes must be set to allow for dialing *98XXX for *
; calls to complete properly. Make sure that vm-local is correct for each box *
;******************************************************************************
exten => *98,1,Answer ;catch *98 and answer the call
exten => *98,2,Wait(1) ;pause for 1 second
exten => *98,3,Read(ex|vm-login|||2|2) ;Read into var ex the val after vm-login message played, 2 attempts, timeout 2 sec.
exten => *98,4,GotoIf($[$["${ex:0:1}" = "1"]]?vm-local,1:vm-remote,1) ;If first digit of ex = 1, goto vm-local else go to vm-remote.
;*************************************************************************************
; Make sure the above local evaluation fits your local extension profile, if you're *
; using 4 digit dialing and your local office common prefix is 42XX, then you'd *
; use this for your evaulation: GotoIf($[$["${ex:0:2}" = "42"]]?vm-local) *
; If you have multiple non-congruous local extension profiles, set the destination *
; of the first evaluation to the next line like so: *
; exten => *98,4,GotoIf($[$["${ex:0:1}" = "2"]]?vm-local,1:5) *
; exten => *98,5,GotoIf($[$["${ex:0:1}" = "6"]]?vm-local,1:vm-remote,1) *
; and so on until all necessary matching conditions are met *
;*************************************************************************************
;*************************************************************************************
; This section catches direct dial *98 numbers like *98XXX and runs the same *
; evaluation as above, make sure this section matches your evaluations above. *
;*************************************************************************************
exten => _*98.,1,Set(ex=${EXTEN:3}) ;Set the variable ex equal to extension # dialed
exten => _*98.,2,GotoIf($[$["${ex:0:1}" = "1"]]?vm-local,1:vm-remote,1) ;If first digit of ex = 1, goto vm-local, else go to vm-remote
;*************************************************************************************
; This section of code is just copied from the original app-dialvm (and renamed with *
; vm-local, since it handles local extensions and their access to voicemail. *
;*************************************************************************************
exten => vm-local,1,Macro(get-vmcontext,${ex}) ;Get the Voicemail Context of the extension
exten => vm-local,2,VoiceMailMain(${ex}@${VMCONTEXT}) ;call VoiceMailMain with extension and context
exten => vm-local,3,Goto(hang,1) ;release the call
;*************************************************************************************
; This section of code sends extensions that evaluate as "remote" to the outbound- *
; allroutes context and sets the dial pattern to *98XXX or whatever your extension *
; happens to be. The dialing rules of the outbound routes will route the call to *
; the proper server in your trunking scheme. *
;*************************************************************************************
exten => vm-remote,1,goto(outbound-allroutes,*98${ex},1) ;send call to outbound routes for trunking.
exten => vm-remote,2,Goto(hang,1) ;release the call
exten => hang,1,Macro(hangupcall,) ;Hang up the call if anything manages to fall through
; end of [app-dialvm]
Wrap-Up and Testing:
That's about it. Obviously these modifications need to be made at each server. The final step is testing. Here is the testing procedure I have in place:
1. Attempt a direct extension dial across the trunk (i.e. call extension 211 from 116) and verify the call goes through
2. Attempt an intercom call across the trunk (assuming you have the paging and intercom features enabled) and verify the call goes through
3. Attempt to park a call to the remote parking lot (if you have this enabled), also verify you can retrieve the call.
4. Dial into your system from the outside (or simulate with 7777) and go to the IVR that has direct dialing enabled, attempt to direct dial a remote extension and verify the call goes through.
5. Dial into your system from the outside (or simulate with 7777) and use the company directory (#) to dial by name, a remote extension. Verify the call goes through.
6. Attempt to use *98XXX to directly dial into a local voicemail box (i.e. *98116 for local extension 116) verify all is operational.
7. Attempt to use *98 to access a local voicemail box (dial *98 and wait for the extension prompt) verify all is operational.
8. Attempt to use *98XXX to directly dial into a remote voicemail box (i.e. *98211 for remote extension 211) verify all is operational.
9. Attempt to use *98 to access a remote voicemail box (dial *98 and wait for the extension prompt) verify all is operational.
10. Perform steps 1 through 9 on each server to verify full functionality.
11. Enjoy your unified voicemail and company directory.
Conclusion:
I want to personally thank everyone who assisted with the original coding for this application. It has developed quite a bit, and I hope it will grow even more. If anyone has improvements, PLEASE POST! This community thrives on user generated content, so let's keep it going!
Regards,
Chris Vanderbles
P.S. I've also updated the WIKI to reference this new guide.
*****UPDATE for Asterisk 1.6 users*******
Thanks to civhamm for sending me an update... apparently asterisk 1.6 likes commas not pipes, so:
correct for 1.4
exten => *98,3,Read(ex|vm-login|||2|2) ;Read into var ex the val after vm-login message played, 2 attempts, timeout 2 sec.
correct as of 1.6
exten => *98,3,Read(ex,vm-login,,,2,2) ;Read into var ex the val after vm-login message played, 2 attempts, timeout 2 sec.

Member Since:
2006-06-26