@ -223,10 +223,10 @@ TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0)
;
; so that dialtone remains even after dialing a 9. Please note that ignorepat
; only works with channels which receive dialtone from the PBX, such as DAHDI,
; Phone, and VPB. Other channels, such as SIP and MGCP, which generate their
; own dialtone and converse with the PBX only after a number is complete, are
; generally unaffected by ignorepat (unless DISA or another method is used to
; generate a dialtone after answering the channel).
; Phone, and VPB. Other channels, such as IAX2, PJSIP, SIP and MGCP, which generate
; generate their own dialtone and converse with the PBX only after a number is
; complete, are generally unaffected by ignorepat (unless DISA or another method
; is used to generate a dialtone after answering the channel).
;
;
@ -241,12 +241,15 @@ TRUNKMSD=1 ; MSD digits to strip (usually 1 or 0)
;exten => 12564286000,1,Gosub(6000,stdexten(IAX2/foo))
;exten => 12564286000,n,Goto(default,s,1) ; exited Voicemail
;exten => _125642860XX,1,Dial(IAX2/otherbox/${EXTEN:7})
;exten => _125642861XX,1,Dial(IAX2/user@example.com/${EXTEN:7})
;exten => _125642862XX,1,Dial(IAX2/user:secret@example.com/${EXTEN:7})
;exten => _125642863XX,1,Dial(IAX2/user:secret:[outkey]@example.com/${EXTEN:7})
[dundi-e164-customers]
;
; If you are an ITSP or Reseller, list your customers here.
;
;exten => _12564286000,1,Dial(SIP/customer1)
;exten => _12564286000,1,Dial(PJ SIP/customer1)
;exten => _12564286001,1,Dial(IAX2/customer2)
[dundi-e164-via-pstn]
@ -279,10 +282,10 @@ switch => DUNDi/e164
include => dundi-e164-local
include => dundi-e164-switch
;
; DUNDi can also be implemented as a Macro instead of using
; DUNDi can also be implemented as a subroutine instead of using
; the Local channel driver.
;
[macro- dundi-e164]
[dundi-e164]
;
; ARG1 is the extension to Dial
;
@ -300,13 +303,10 @@ exten => s,1,Goto(${ARG1},1)
include => dundi-e164-lookup
;
; Here are the entries you need to participate in the IAXTEL
; call routing system. Most IAXTEL numbers begin with 1-700, but
; there are exceptions. For more information, and to sign
; up, please go to www.gnophone.com or www.iaxtel.com
; Here is how to make a call to another Asterisk server using the IAX2 protocol
;
[iaxtel700 ]
exten => _91700XXXXXXX,1,Dial(IAX2/${GLOBAL(IAXINFO)}@iaxtel.com/${EXTEN:1}@iaxtel )
[iax2-trunk]
exten => _555XXXX,1,Dial(IAX2/username:secret@example.com/${EXTEN}@some-dialplan-context)
;
; The SWITCH statement permits a server to share the dialplan with
@ -321,14 +321,15 @@ exten => _91700XXXXXXX,1,Dial(IAX2/${GLOBAL(IAXINFO)}@iaxtel.com/${EXTEN:1}@iaxt
;
; International long distance through trunk
;
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
exten => _9011.,1,Gosub(dundi-e164,s,1(${EXTEN:4}))
; same => n,Hangup()
exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})
[trunkld]
;
; Long distance context accessed through trunk
;
exten => _91NXXNXXXXXX,1,Macro(dundi-e164,${EXTEN:1} )
exten => _91NXXNXXXXXX,1,Gosub(dundi-e164,s,1(${EXTEN:1}) )
exten => _91NXXNXXXXXX,n,Dial(${GLOBAL(TRUNK)}/${EXTEN:${GLOBAL(TRUNKMSD)}})
[trunklocal]
@ -421,36 +422,46 @@ exten => _XXXXXX*X!,1,Goto(outbound-freenum2,${EXTEN},1)
; from the [outbound-freenum] context
;
exten => _X!,1,Verbose(2,Performing ISN lookup for ${EXTEN})
same => n,Set(SUFFIX=${CUT(EXTEN,*,2-)}) ; make sure the suffix is all digits as well
same => n,GotoIf($["${FILTER(0-9,${SUFFIX})}" != "${SUFFIX}"]?fn-CONGESTION,1)
same => n,Set(SUFFIX=${CUT(EXTEN,*,2-)}) ; make sure the suffix is all digits as well
same => n,GotoIf($["${FILTER(0-9,${SUFFIX})}" != "${SUFFIX}"]?fn-CONGESTION,1)
; filter out bad characters per the README-SERIOUSLY.best-practices.txt document
same => n,Set(TIMEOUT(absolute)=10800)
same => n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,,1,freenum.org)}) ; perform our lookup with freenum.org
same => n,GotoIf($["${isnresult}" != ""]?from)
same => n,Set(DIALSTATUS=CONGESTION)
same => n,Goto(fn-CONGESTION,1)
same => n(from),Set(__SIPFROMUSER=${CALLERID(num)})
same => n,GotoIf($["${GLOBAL(FREENUMDOMAIN)}" = ""]?dial) ; check if we set the FREENUMDOMAIN global variable in [global]
same => n,Set(__SIPFROMDOMAIN=${GLOBAL(FREENUMDOMAIN)}) ; if we did set it, then we'll use it for our outbound dialing domain
same => n(dial),Dial(SIP/${isnresult},40)
same => n,Goto(fn-${DIALSTATUS},1)
same => n,Set(TIMEOUT(absolute)=10800)
same => n,Set(isnresult=${ENUMLOOKUP(${EXTEN},sip,,1,freenum.org)}) ; perform our lookup with freenum.org
same => n,GotoIf($["${isnresult}" != ""]?from)
same => n,Set(DIALSTATUS=CONGESTION)
same => n,Goto(fn-CONGESTION,1)
same => n(from),Set(__SIPFROMUSER=${CALLERID(num)})
same => n,GotoIf($["${GLOBAL(FREENUMDOMAIN)}" = ""]?dial) ; check if we set the FREENUMDOMAIN global variable in [global]
same => n,Set(__SIPFROMDOMAIN=${GLOBAL(FREENUMDOMAIN)}) ; if we did set it, then we'll use it for our outbound dialing domain
same => n(dial),Dial(SIP/${isnresult},40)
same => n,Goto(fn-${DIALSTATUS},1)
exten => fn-BUSY,1,Busy()
exten => _f[n]-.,1,NoOp(ISN: ${DIALSTATUS})
same => n,Congestion()
[macro- trunkdial]
[trunkdial]
;
; Standard trunk dial macro (hangs up on a dialstatus that should
; Standard trunk dial subroutine (hangs up on a dialstatus that should
; terminate call)
; ${ARG1} - What to dial
;
exten => s,1,Dial(${ARG1})
exten => s,1,StackPop()
same => n,Dial(${ARG1})
exten => s,n,Goto(s-${DIALSTATUS},1)
exten => s-NOANSWER,1,Hangup()
exten => s-BUSY,1,Hangup()
exten => _s-.,1,NoOp
exten => s-BUSY,1,PlayTones(busy)
same => n,Wait(60)
same => n,Hangup()
exten => s-CHANUNAVAIL,1,PlayTones(congestion)
same => n,Wait(60)
same => n,Hangup()
exten => s-CONGESTION,1,PlayTones(congestion)
same => n,Wait(60)
same => n,Hangup()
exten => _s-.,1,NoOp(${DIALSTATUS})
same => n,Hangup()
[stdexten]
;
@ -471,18 +482,18 @@ exten => _s-.,1,NoOp
; previous value (before being declared as LOCAL()) upon Return.
;
exten => _X.,50000(stdexten),NoOp(Start stdexten)
exten => _X., n,Set(LOCAL(ext)=${EXTEN})
exten => _X., n,Set(LOCAL(dev)=${ARG1})
exten => _X., n,Set(LOCAL(cntx)=${ARG2})
exten => _X., n,Set(LOCAL(mbx)=${ext}${IF($[!${ISNULL(${cntx})}]?@${cntx})})
exten => _X., n,Dial(${dev},20) ; Ring the interface, 20 seconds maximum
exten => _X., n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
same => n,Set(LOCAL(ext)=${EXTEN})
same => n,Set(LOCAL(dev)=${ARG1})
same => n,Set(LOCAL(cntx)=${ARG2})
same => n,Set(LOCAL(mbx)=${ext}${IF($[!${ISNULL(${cntx})}]?@${cntx})})
same => n,Dial(${dev},20) ; Ring the interface, 20 seconds maximum
same => n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce
exten => stdexten-NOANSWER, n,Return() ; If they press #, return to start
same => n,Return() ; If they press #, return to start
exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce
exten => stdexten-BUSY, n,Return() ; If they press #, return to start
sam e => n,Return() ; If they press #, return to start
exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer
@ -501,24 +512,24 @@ exten => a,n,Return()
; See above note in stdexten about priority handling on exit.
;
exten => _X.,60000(stdPrivacyexten),NoOp(Start stdPrivacyexten)
exten => _X., n,Set(LOCAL(ext)=${ARG1})
exten => _X., n,Set(LOCAL(dev)=${ARG2})
exten => _X., n,Set(LOCAL(dontcntx)=${ARG3})
exten => _X., n,Set(LOCAL(tortcntx)=${ARG4})
exten => _X., n,Set(LOCAL(cntx)=${ARG5})
same => n,Set(LOCAL(ext)=${ARG1})
same => n,Set(LOCAL(dev)=${ARG2})
same => n,Set(LOCAL(dontcntx)=${ARG3})
same => n,Set(LOCAL(tortcntx)=${ARG4})
same => n,Set(LOCAL(cntx)=${ARG5})
exten => _X.,n,Set(LOCAL(mbx)="${ext}"$["${cntx}" ? "@${cntx}" :: ""])
exten => _X., n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening
same => n,Dial(${dev},20,p) ; Ring the interface, 20 seconds maximum, call screening
; option (or use P for databased call _X.screening)
exten => _X., n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
same => n,Goto(stdexten-${DIALSTATUS},1) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
exten => stdexten-NOANSWER,1,VoiceMail(${mbx},u) ; If unavailable, send to voicemail w/ unavail announce
exten => stdexten-NOANSWER, n,NoOp(Finish stdPrivacyexten NOANSWER)
exten => stdexten-NOANSWER, n,Return() ; If they press #, return to start
same => n,NoOp(Finish stdPrivacyexten NOANSWER)
same => n,Return() ; If they press #, return to start
exten => stdexten-BUSY,1,VoiceMail(${mbx},b) ; If busy, send to voicemail w/ busy announce
exten => stdexten-BUSY, n,NoOp(Finish stdPrivacyexten BUSY)
exten => stdexten-BUSY, n,Return() ; If they press #, return to start
sam e => n,NoOp(Finish stdPrivacyexten BUSY)
sam e => n,Return() ; If they press #, return to start
exten => stdexten-DONTCALL,1,Goto(${dontcntx},s,1) ; Callee chose to send this call to a polite "Don't call again" script.
@ -527,24 +538,22 @@ exten => stdexten-TORTURE,1,Goto(${tortcntx},s,1) ; Callee chose to send this ca
exten => _stde[x]te[n]-.,1,Goto(stdexten-NOANSWER,1) ; Treat anything else as no answer
exten => a,1,VoiceMailMain(${mbx}) ; If they press *, send the user into VoicemailMain
exten => a, n,Return()
same => n,Return()
[macro -page]
[sub -page]
;
; Paging macro :
; Paging subroutine :
;
; Check to see if SIP device is in use and DO NOT PAGE if they are
;
; ${ARG1} - Device to page
exten => s,1,ChanIsAvail(${ARG1},s) ; s is for ANY call
exten => s,n,GotoIf($[${AVAILSTATUS} = "1"]?autoanswer:fail)
exten => s,n(autoanswer),Set(_ALERT_INFO="RA") ; This is for the PolyComs
exten => s,n,SIPAddHeader(Call-Info: Answer-After=0) ; This is for the Grandstream, Snoms, and Others
exten => s,n,NoOp() ; Add others here and Post on the Wiki!!!!
exten => s,n,Dial(${ARG1})
exten => s,n(fail),Hangup()
same => n,GotoIf($["${AVAILSTATUS}" = "1"]?autoanswer:fail)
same => n(autoanswer),Set(_ALERT_INFO="RA") ; This is for the PolyComs
same => n,SIPAddHeader(Call-Info: Answer-After=0) ; This is for the Grandstream, Snoms, and Others
same => n,NoOp() ; Add others here and Post on the Wiki!!!!
same => n,Dial(${ARG1})
same => n(fail),Hangup()
[demo]
include => stdexten
@ -552,18 +561,18 @@ include => stdexten
; We start with what to do when a call first comes in.
;
exten => s,1,Wait(1) ; Wait a second, just for fun
exten => s, n,Answer() ; Answer the line
exten => s, n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
exten => s, n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
exten => s, n(restart),BackGround(demo-congrats) ; Play a congratulatory message
exten => s, n(instruct),BackGround(demo-instruct) ; Play some instructions
exten => s, n,WaitExten() ; Wait for an extension to be dialed.
same => n,Answer() ; Answer the line
same => n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
same => n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
same => n(restart),BackGround(demo-congrats) ; Play a congratulatory message
same => n(instruct),BackGround(demo-instruct) ; Play some instructions
same => n,WaitExten() ; Wait for an extension to be dialed.
exten => 2,1,BackGround(demo-moreinfo) ; Give some more information.
exten => 2,n,Goto(s,instruct)
exten => 3,1,Set(CHANNEL(language)=fr) ; Set language to french
exten => 3, n,Goto(s,restart) ; Start with the congratulations
same => n,Goto(s,restart) ; Start with the congratulations
exten => 1000,1,Goto(default,s,1)
;
@ -572,19 +581,19 @@ exten => 1000,1,Goto(default,s,1)
;
exten => 1234,1,Playback(transfer,skip) ; "Please hold while..."
; (but skip if channel is not up)
exten => 1234, n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
exten => 1234, n,Goto(default,s,1) ; exited Voicemail
same => n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
same => n,Goto(default,s,1) ; exited Voicemail
exten => 1235,1,VoiceMail(1234,u) ; Right to voicemail
exten => 1236,1,Dial(Console/dsp) ; Ring forever
exten => 1236, n,VoiceMail(1234,b) ; Unless busy
same => n,VoiceMail(1234,b) ; Unless busy
;
; # for when they're done with the demo
;
exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo"
exten => #, n,Hangup() ; Hang them up.
same => n,Hangup() ; Hang them up.
;
; A timeout and "invalid extension rule"
@ -597,64 +606,65 @@ exten => i,1,Playback(invalid) ; "That's not valid, try again"
; Asterisk demo.
;
exten => 500,1,Playback(demo-abouttotry) ; Let them know what's going on
exten => 500, n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo
exten => 500, n,Playback(demo-nogo) ; Couldn't connect to the demo site
exten => 500, n,Goto(s,6) ; Return to the start over message.
same => n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo
same => n,Playback(demo-nogo) ; Couldn't connect to the demo site
same => n,Goto(s,6) ; Return to the start over message.
;
; Create an extension, 600, for evaluating echo latency.
;
exten => 600,1,Playback(demo-echotest) ; Let them know what's going on
exten => 600, n,Echo() ; Do the echo test
exten => 600, n,Playback(demo-echodone) ; Let them know it's over
exten => 600, n,Goto(s,6) ; Start over
same => n,Echo() ; Do the echo test
same => n,Playback(demo-echodone) ; Let them know it's over
same => n,Goto(s,6) ; Start over
;
; You can use the Macro Pag e to intercom a individual user
exten => 76245,1,Macro(page,SIP/Grandstream1 )
; You can use the page subroutin e to intercom a individual user
exten => 76245,1,Gosub(page,s,1(SIP/Grandstream1) )
; or if your peernames are the same as extensions
exten => _7XXX,1,Macro(page,SIP/${EXTEN} )
exten => _7XXX,1,Gosub(page,s,1(SIP/${EXTEN}) )
;
;
; System Wide Page at extension 7999
;
exten => 7999,1,Set(TIMEOUT(absolute)=60)
exten => 7999,2 ,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)
same => n ,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)
; Give voicemail at extension 8500
;
exten => 8500,1,VoiceMailMain()
exten => 8500, n,Goto(s,6)
same => n,Goto(s,6)
;
; Here's what a phone entry would look like (IXJ for example)
;
;exten => 1265,1,Dial(Phone/phone0,15)
;exten => 1265, n,Goto(s,5)
; same => n,Goto(s,5)
;
; The page context calls up the page macro that sets variables needed for auto-answer
; The page context calls up the sub-page subroutine that sets variables needed for auto-answer
; It is in is own context to make calling it from the Page() application as simple as
; Local/{peername}@page
;
[page]
exten => _X.,1,Macro(page,SIP/${EXTEN})
exten => _X.,1,Gosub(sub-page,s,1(SIP/${EXTEN}))
same => n,Hangup()
;[mainmenu]
;
; Example "main menu" context with submenu
;
;exten => s,1,Answer
;exten => s, n,Background(thanks) ; "Thanks for calling press 1 for sales, 2 for support, ..."
;exten => s, n,WaitExten
; same => n,Background(thanks) ; "Thanks for calling press 1 for sales, 2 for support, ..."
; same => n,WaitExten
;exten => 1,1,Goto(submenu,s,1)
;exten => 2,1,Hangup
;include => default
;
;[submenu]
;exten => s,1,Ringing ; Make them comfortable with 2 seconds of ringback
;exten => s, n,Wait,2
;exten => s, n,Background(submenuopts) ; "Thanks for calling the sales department. Press 1 for steve, 2 for..."
;exten => s, n,WaitExten
; same => n,Wait,2
; same => n,Background(submenuopts) ; "Thanks for calling the sales department. Press 1 for steve, 2 for..."
; same => n,WaitExten
;exten => 1,1,Goto(default,steve,1)
;exten => 2,1,Goto(default,mark,2)
@ -704,7 +714,7 @@ include => demo
;exten => mark,1,Goto(6275,1) ; alias mark to 6275
;exten => 6536,1,Gosub(${EXTEN},stdexten(${WIL}))
; Ditto for wil
;exten => 6536, n,Goto(default,s,1) ; exited Voicemail
; same => n,Goto(default,s,1) ; exited Voicemail
;exten => wil,1,Goto(6236,1)
;If you want to subscribe to the status of a parking space, this is
@ -727,7 +737,7 @@ include => demo
; voicemailmain
;
;exten => 8500,1,VoicemailMain
;exten => 8500, n,Hangup
; same => n,Hangup
;
; Or a conference room (you'll need to edit meetme.conf to enable this room)
;
@ -743,17 +753,18 @@ include => demo
; this is the context that your incoming IAX/SIP trunk dumps you in...
;[acme-incoming]
;exten => s,1,Wait(1)
;exten => s,n,Answer()
;exten => s,n(menu),Playback(acme/vm-brief-menu)
;exten => s,n(exten),Background(vm-enter-num-to-call)
;exten => s,n,WaitExten(5)
;exten => s,n(goodbye),Playback(vm-goodbye)
;exten => s,n(end),Hangup()
; same => n,Answer() ; "same" allows you to continue an extension more
; concisely without having to repeat the extension or pattern
; same => n(menu),Playback(acme/vm-brief-menu)
; same => n(exten),Background(vm-enter-num-to-call)
; same => n,WaitExten(5)
; same => n(goodbye),Playback(vm-goodbye)
; same => n(end),Hangup()
;
;include => acme-extens
;
;exten => i,1,Playback(vm-invalid)
;exten => i, n,Goto(s,exten) ; optionally, transfer to operator
; same => n,Goto(s,exten) ; optionally, transfer to operator
;
;exten => t,1,Goto(s,goodbye)
;
@ -761,10 +772,10 @@ include => demo
;
;[acme-internal]
;exten => s,1,Answer()
;exten => s, n(exten),Background(vm-enter-num-to-call)
;exten => s, n,WaitExten(5)
;exten => s, n(goodbye),Playback(vm-goodbye)
;exten => s, n(end),Hangup()
; same => n(exten),Background(vm-enter-num-to-call)
; same => n,WaitExten(5)
; same => n(goodbye),Playback(vm-goodbye)
; same => n(end),Hangup()
;
;include => trunkint
;include => trunkld
@ -780,10 +791,10 @@ include => demo
;[acme-extens]
;include => stdexten
;exten => 111,1,Gosub(111,stdexten(SIP/pete_1,acme))
;exten => 111, n,Goto(s,exten)
; same => n,Goto(s,exten)
;
;exten => 112,1,Gosub(112,stdexten(SIP/nancy_1,acme))
;exten => 112, n,Goto(s,end)
; same => n,Goto(s,end)
;
; end of acme example
@ -823,20 +834,20 @@ include => demo
[time]
exten => _X.,30000(time),NoOp(Time: ${EXTEN} ${timezone})
exten => _X., n,Wait(0.25)
exten => _X., n,Answer()
same => n,Wait(0.25)
same => n,Answer()
; the amount of delay is set for English; you may need to adjust this time
; for other languages if there's no pause before the synchronizing beep.
exten => _X., n,Set(FUTURETIME=$[${EPOCH} + 12])
exten => _X., n,SayUnixTime(${FUTURETIME},Zulu,HNS)
exten => _X., n,SayPhonetic(z)
same => n,Set(FUTURETIME=$[${EPOCH} + 12])
same => n,SayUnixTime(${FUTURETIME},Zulu,HNS)
same => n,SayPhonetic(z)
; use the timezone associated with the extension (sip only), or system-wide
; default if one hasn't been set.
exten => _X., n,SayUnixTime(${FUTURETIME},${timezone},HNS)
exten => _X., n,Playback(spy-local)
exten => _X., n,WaitUntil(${FUTURETIME})
exten => _X., n,Playback(beep)
exten => _X., n,Return()
same => n,SayUnixTime(${FUTURETIME},${timezone},HNS)
same => n,Playback(spy-local)
same => n,WaitUntil(${FUTURETIME})
same => n,Playback(beep)
same => n,Return()
;
; ANI context: use in the same way as "time" above
@ -844,13 +855,13 @@ exten => _X.,n,Return()
[ani]
exten => _X.,40000(ani),NoOp(ANI: ${EXTEN})
exten => _X., n,Wait(0.25)
exten => _X., n,Answer()
exten => _X., n,Playback(vm-from)
exten => _X., n,SayDigits(${CALLERID(ani)})
exten => _X., n,Wait(1.25)
exten => _X., n,SayDigits(${CALLERID(ani)}) ; playback again in case of missed digit
exten => _X., n,Return()
same => n,Wait(0.25)
same => n,Answer()
same => n,Playback(vm-from)
same => n,SayDigits(${CALLERID(ani)})
same => n,Wait(1.25)
same => n,SayDigits(${CALLERID(ani)}) ; playback again in case of missed digit
same => n,Return()
; For more information on applications, just type "core show applications" at your
; friendly Asterisk CLI prompt.