<div>Segue sip.conf e extension.conf..... Att, Deisy</div>
<div>
<p>; Note: If your SIP devices are behind a NAT and your Asterisk<br>;&nbsp; server isn&#39;t, try adding &quot;nat=1&quot; to each peer definition to<br>;&nbsp; solve translation problems.</p>
<p>[general]</p>
<p>bindport=5060&nbsp;&nbsp;&nbsp;; UDP Port to bind to (SIP standard port is 5060)<br>bindaddr=<a href="http://0.0.0.0">0.0.0.0</a>&nbsp;&nbsp;; IP address to bind to (<a href="http://0.0.0.0">0.0.0.0</a> binds to all)<br>disallow=all<br>allow=g723,g729,gsm
<br>;allow=alaw<br>context = from-sip-external ; Send unknown SIP callers to this context<br>callerid = Unknown<br>tos=throughput</p>
<p><br>#include sip_nat.conf<br>#include sip_custom.conf<br>#include sip_additional.conf<br>#include additional_a2billing_sip.conf</p>
<p>--------------------------------------------------------------</p>
<p>; include extension contexts generated from AMP<br>#include extensions_additional.conf</p>
<p>; Customizations to this dialplan should be made in extensions_custom.conf<br>; See extensions_custom.conf.sample for an example<br>#include extensions_custom.conf</p>
<p>[from-trunk]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; just an alias since VoIP shouldn&#39;t be called PSTN<br>include =&gt; from-pstn</p>
<p>[from-pstn]<br>include =&gt; from-pstn-custom&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; create this context in extensions_custom.conf to include customizations<br>include =&gt; ext-did<br>exten =&gt; fax,1,Goto(ext-fax,in_fax,1)</p>
<p><br>; ############################################################################<br>; Macros [macro]<br>; ############################################################################</p>
<p>; Rings one or more extensions.&nbsp; Handles things like call forwarding and DND<br>; We don&#39;t call dial directly for anything internal anymore.<br>; ARGS: $TIMER, $OPTIONS, $EXT1, $EXT2, $EXT3, ...<br>; Use a Macro call such as the following: 
<br>;&nbsp; Macro(dial,$DIAL_TIMER,$DIAL_OPTIONS,$EXT1,$EXT2,$EXT3,...)<br>[macro-dial]<br>;exten =&gt; s,1,GotoIf($[ &quot;${MACRO_CONTEXT}&quot; = &quot;macro-rg-group&quot; ]?4:2)&nbsp; ; if this is from rg-group, don&#39;t strip prefix
<br>;exten =&gt; s,2,GotoIf($[&quot;${CALLERID(name):0:${LEN(${RGPREFIX})}}&quot; != &quot;${RGPREFIX}&quot;]?4:3)&nbsp; ; check for ring-group prefix<br>;exten =&gt; s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off prefix
<br>exten =&gt; s,1,AGI,dialparties.agi<br>exten =&gt; s,2,NoOp(Returned from dialparties with no extensions to call)<br>exten =&gt; s,3,Set(DIALSTATUS=BUSY)<br>exten =&gt; s,10,Dial(${ds})&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; dialparties will set the priority to 10 if $ds is not null
<br>exten =&gt; s,20,NoOp(Returned from dialparties with hunt groups to dial )<br>exten =&gt; s,21,Set(HuntLoop=0)<br>exten =&gt; s,22,GotoIf($[${HuntMembers} &gt;= 1]?30 )&nbsp; ; if this is from rg-group, don&#39;t strip prefix
<br>exten =&gt; s,23,NoOp(Returning there are no members left in the hunt group to ring)</p>
<p>exten =&gt; s,30,Set(HuntMember=HuntMember${HuntLoop})<br>exten =&gt; s,31,GotoIf($[$[&quot;${CALLTRACE_HUNT}&quot; != &quot;&quot; ] &amp; $[&quot;${RingGroupMethod}&quot; = &quot;hunt&quot; ]]?32:35 )&nbsp; ; Set CAll Trace for Hunt member we are going to call
<br>&nbsp;&nbsp;exten =&gt; s,32,Set(CT_EXTEN=${CUT(ARG3,,$[${HuntLoop} + 1])})<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,33,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,34,Goto(s,42)</p>
<p>exten =&gt; s,35,GotoIf($[$[&quot;${CALLTRACE_HUNT}&quot; != &quot;&quot; ] &amp; $[&quot;${RingGroupMethod}&quot; = &quot;memoryhunt&quot; ]]?36:50 )&nbsp; ;Set Call Trace for each hunt member we are going to call &quot;Memory groups have multiple members to set CALL TRACE For hence the loop
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,36,Set(CTLoop=0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,37,GotoIf($[${CTLoop} &gt; ${HuntLoop}]?42 )&nbsp; ; if this is from rg-group, don&#39;t strip prefix<br>&nbsp;&nbsp;exten =&gt; s,38,Set(CT_EXTEN=${CUT(ARG3,,$[${CTLoop} + 1])})
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,39,Set(DB(CALLTRACE/${CT_EXTEN})=${CALLTRACE_HUNT})<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,40,Set(CTLoop=$[1 + ${CTLoop}])<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exten =&gt; s,41,Goto(s,37)<br>exten =&gt; s,42,Dial(${${HuntMember}}${ds} ) ; dialparties will set the priority to 20 if $ds is not null and its a hunt group
<br>exten =&gt; s,43,Set(HuntLoop=$[1 + ${HuntLoop}])<br>exten =&gt; s,44,Set(HuntMembers=$[${HuntMembers} - 1])<br>exten =&gt; s,45,Goto(s,22)<br>exten =&gt; s,50,DBdel(CALLTRACE/${CT_EXTEN})<br>exten =&gt; s,51,Goto(s,42)
</p>
<p><br>;exten =&gt; s,1,GotoIf($[ &quot;${MACRO_CONTEXT}&quot; = &quot;macro-rg-group&quot; ]?4:2)&nbsp; ; if this is from rg-group, don&#39;t strip prefix<br>;exten =&gt; s,2,GotoIf($[${CALLERID(name):0:${LEN(${RGPREFIX})}} != ${RGPREFIX}]?4:3)&nbsp; ; check for ring-group prefix
<br>;exten =&gt; s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off prefix<br>;exten =&gt; s,4,AGI,dialparties.agi<br>;exten =&gt; s,5,NoOp(Returned from dialparties with no extensions to call)<br>;exten =&gt; s,6,Set(DIALSTATUS=BUSY)
<br>;exten =&gt; s,10,Dial(${ds})&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; dialparties will set the priority to 10 if $ds is not null</p>
<p>; Ring an extension, if the extension is busy or there is no answer send it<br>; to voicemail<br>; ARGS: $VMBOX, $EXT<br>[macro-exten-vm]<br>exten =&gt; s,1,Macro(user-callerid)<br>exten =&gt; s,2,Set(FROMCONTEXT=exten-vm)
<br>exten =&gt; s,3,Macro(record-enable,${ARG2},IN)<br>exten =&gt; s,4,Macro(dial,${RINGTIMER},${DIAL_OPTIONS},${ARG2})<br>exten =&gt; s,5,GotoIf($[&quot;${CHANNEL:0:5}&quot; = &quot;Local&quot;]?s-${DIALSTATUS},1) ; if the channel is Local, then do not go to voicemail.&nbsp; This is primarily to avoid vm for call-forwarded extensions in ring groups
<br>exten =&gt; s,6,GotoIf($[&quot;${ARG1}&quot; = &quot;novm&quot;]?s-${DIALSTATUS},1) ; no voicemail in use for this extension<br>exten =&gt; s,7,NoOp(Sending to Voicemail box ${ARG2})<br>exten =&gt; s,8,Macro(vm,${ARG1},${DIALSTATUS})
<br>exten =&gt; s-BUSY,1,NoOp(Extension is reporting BUSY and has no Voicemail)<br>exten =&gt; s-BUSY,2,Busy()<br>exten =&gt; s-BUSY,3,Wait(60)<br>exten =&gt; s-BUSY,4,NoOp()<br>exten =&gt; _s-.,1,Congestion()</p>
<p>[macro-vm]<br>exten =&gt; s,1,Macro(user-callerid)<br>exten =&gt; s,2,Goto(s-${ARG2},1)<br>exten =&gt; s-BUSY,1,Macro(get-vmcontext,${ARG1})<br>exten =&gt; s-BUSY,2,Voicemail(<a href="mailto:b${ARG1}@${VMCONTEXT">b${ARG1}@${VMCONTEXT
</a>})&nbsp;&nbsp; ; Voicemail Busy message<br>exten =&gt; s-BUSY,3,Hangup()<br>exten =&gt; _s-.,1,Macro(get-vmcontext,${ARG1})<br>exten =&gt; _s-.,2,Voicemail(<a href="mailto:u${ARG1}@${VMCONTEXT">u${ARG1}@${VMCONTEXT</a>})&nbsp;&nbsp;&nbsp;&nbsp; ; Voicemail Unavailable message
<br>exten =&gt; _s-.,3,Hangup()<br>exten =&gt; o,1,Background(one-moment-please)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; 0 during vm message will hangup<br>exten =&gt; o,2,GotoIf($[&quot;foo${FROM_DID}&quot; = &quot;foo&quot;]?from-pstn,s,1:from-pstn,${FROM_DID},1)
<br>exten =&gt; a,1,Macro(get-vmcontext,${ARG1})<br>exten =&gt; a,2,VoiceMailMain(<a href="mailto:${ARG1}@${VMCONTEXT">${ARG1}@${VMCONTEXT</a>})<br>exten =&gt; a,3,Hangup</p>
<p>; get the voicemail context for the user in ARG1<br>[macro-get-vmcontext]<br>exten =&gt; s,1,Set(VMCONTEXT=${DB(AMPUSER/${ARG1}/voicemail)})<br>exten =&gt; s,2,GotoIf($[&quot;foo${VMCONTEXT}&quot; = &quot;foo&quot;]?200:300)
<br>exten =&gt; s,200,Set(VMCONTEXT=default)<br>exten =&gt; s,300,NoOp()</p>
<p>; For some reason, if I don&#39;t run setCIDname, CALLERID(name) will be blank in my AGI<br>; ARGS: none<br>[macro-fixcid]<br>exten =&gt; s,1,Set(CALLERID(name)=${CALLERID(name)})</p>
<p>; Ring groups of phones<br>; ARGS: comma separated extension list<br>; 1 - Ring Group Strategy<br>; 2 - ringtimer<br>; 3 - prefix<br>; 4 - extension list<br>[macro-rg-group]<br>exten =&gt; s,1,Macro(user-callerid)<br>
exten =&gt; s,2,GotoIf($[&quot;${CALLERID(name):0:${LEN(${RGPREFIX})}}&quot; != &quot;${RGPREFIX}&quot;]?4:3)&nbsp; ; check for old prefix<br>exten =&gt; s,3,Set(CALLERID(name)=${CALLERID(name):${LEN(${RGPREFIX})}}) ; strip off old prefix
<br>exten =&gt; s,4,Set(RGPREFIX=${ARG3})&nbsp; ; set new prefix<br>exten =&gt; s,5,Set(CALLERID(name)=${RGPREFIX}${CALLERID(name)})&nbsp; ; add prefix to callerid name<br>exten =&gt; s,6,Set(RecordMethod=Group)&nbsp; ; set new prefix<br>
exten =&gt; s,7,Macro(record-enable,${MACRO_EXTEN},${RecordMethod})<br>exten =&gt; s,8,Set(RingGroupMethod=${ARG1})&nbsp;&nbsp;&nbsp;&nbsp; ;<br>exten =&gt; s,9,Macro(dial,${ARG2},${DIAL_OPTIONS},${ARG4})<br>exten =&gt; s,10,Set(RingGroupMethod=&#39;&#39;)&nbsp;&nbsp;&nbsp;&nbsp; ;
</p>
<p><br>;<br>; Outgoing channel(s) are busy ... inform the client<br>;<br>[macro-outisbusy]<br>exten =&gt; s,1,Playback(all-circuits-busy-now)<br>exten =&gt; s,2,Playback(pls-try-call-later)<br>exten =&gt; s,3,Macro(hangupcall)
</p>
<p>; What to do on hangup.<br>[macro-hangupcall]<br>exten =&gt; s,1,ResetCDR(w)<br>exten =&gt; s,2,NoCDR()<br>exten =&gt; s,3,Wait(5)<br>exten =&gt; s,4,Hangup</p>
<p>[macro-faxreceive]<br>exten =&gt; s,1,Set(FAXFILE=/var/spool/asterisk/fax/${UNIQUEID}.tif)<br>exten =&gt; s,2,Set(EMAILADDR=${FAX_RX_EMAIL})<br>exten =&gt; s,3,rxfax(${FAXFILE})<br>exten =&gt; s,103,Set(EMAILADDR=${FAX_RX_EMAIL})
<br>exten =&gt; s,104,Goto(3)</p>
<p>; dialout and strip the prefix<br>[macro-dialout]<br>exten =&gt; s,1,Macro(user-callerid)<br>exten =&gt; s,2,GotoIf($[&quot;${ECID${CALLERID(number)}}&quot; = &quot;&quot;]?5) &nbsp;;check for CID override for exten<br>exten =&gt; s,3,Set(CALLERID(all)=${ECID${CALLERID(number)}})
<br>exten =&gt; s,4,Goto(7)<br>exten =&gt; s,5,GotoIf($[&quot;${OUTCID_${ARG1}}&quot; = &quot;&quot;]?7) &nbsp;&nbsp;;check for CID override for trunk<br>exten =&gt; s,6,Set(CALLERID(all)=${OUTCID_${ARG1}})<br>exten =&gt; s,7,Set(length=${LEN(${DIAL_OUT_${ARG1}})})
<br>exten =&gt; s,8,Dial(${OUT_${ARG1}}/${ARG2:${length}})<br>exten =&gt; s,9,Congestion<br>exten =&gt; s,109,Macro(outisbusy)</p>
<p><br>; dialout using default OUT trunk - no prefix<br>[macro-dialout-default]<br>exten =&gt; s,1,Macro(user-callerid)<br>exten =&gt; s,2,Macro(record-enable,${CALLERID(number)},OUT)<br>exten =&gt; s,3,Macro(outbound-callerid,${ARG1})
<br>exten =&gt; s,4,Dial(${OUT}/${ARG1})<br>exten =&gt; s,5,Congestion<br>exten =&gt; s,105,Macro(outisbusy)</p>
<p>; dialout using a trunk, using pattern matching (don&#39;t strip any prefix)<br>; arg1 = trunk number, arg2 = number, arg3 = route password<br>[macro-dialout-trunk]<br>exten =&gt; s,1,GotoIf($[&quot;${ARG3}&quot; = &quot;&quot;]?3:2)&nbsp;; arg3 is pattern password
<br>exten =&gt; s,2,Authenticate(${ARG3})<br>exten =&gt; s,3,Macro(user-callerid)<br>exten =&gt; s,4,Macro(record-enable,${CALLERID(number)},OUT)<br>exten =&gt; s,5,Macro(outbound-callerid,${ARG1})<br>exten =&gt; s,6,Set(GROUP()=OUT_${ARG1})
<br>exten =&gt; s,7,GotoIf($[ ${GROUP_COUNT()} &gt; ${OUTMAXCHANS_${ARG1}} ]?108)<br>; if we&#39;ve used up the max channels, continue at (n+101)<br>exten =&gt; s,8,Set(DIAL_NUMBER=${ARG2})<br>exten =&gt; s,9,Set(DIAL_TRUNK=${ARG1})
<br>exten =&gt; s,10,AGI(fixlocalprefix) ; this sets DIAL_NUMBER to the proper dial string for this trunk<br>exten =&gt; s,11,Set(OUTNUM=${OUTPREFIX_${ARG1}}${DIAL_NUMBER})&nbsp; ; OUTNUM is the final dial number<br>exten =&gt; s,12,Set(custom=${CUT(OUT_${ARG1},:,1)})&nbsp; ; Custom trunks are prefixed with &quot;AMP:&quot;
<br>exten =&gt; s,13,GotoIf($[&quot;${custom}&quot; = &quot;AMP&quot;]?16)<br>exten =&gt; s,14,Dial(${OUT_${ARG1}}/${OUTNUM}|120|W)&nbsp; ; Regular Trunk Dial, allow recording.<br>exten =&gt; s,15,Goto(s-${DIALSTATUS},1)</p>
<p>; This is a custom trunk.&nbsp; Substitute $OUTNUM$ with the actual number and rebuild the dialstring<br>; example trunks: &quot;AMP:CAPI/XXXXXXXX:b$OUTNUM$,30,r&quot;, &quot;AMP:OH323/$OUTNUM$@XX.XX.XX.XX:XXXX&quot;<br>exten =&gt; s,16,Set(pre_num=${CUT(OUT_${ARG1},$,1)})
<br>exten =&gt; s,17,Set(the_num=${CUT(OUT_${ARG1},$,2)})&nbsp; ; this is where we expect to find string OUTNUM<br>exten =&gt; s,18,Set(post_num=${CUT(OUT_${ARG1},$,3)})<br>exten =&gt; s,19,GotoIf($[&quot;${the_num}&quot; = &quot;OUTNUM&quot;]?20:21) ; if we didn&#39;t find &quot;OUTNUM&quot;, then skip to Dial
<br>exten =&gt; s,20,Set(the_num=${OUTNUM}) ; replace &quot;OUTNUM&quot; with the actual number to dial<br>exten =&gt; s,21,Dial(${pre_num:4}${the_num}${post_num})<br>exten =&gt; s,22,Goto(s-${DIALSTATUS},1)</p>
<p>exten =&gt; s,108,Noop(max channels used up)<br>exten =&gt; s-BUSY,1,NoOp(Trunk is reporting BUSY)<br>exten =&gt; s-BUSY,2,Busy()<br>exten =&gt; s-BUSY,3,Wait(60)<br>exten =&gt; s-BUSY,4,NoOp()</p>
<p>exten =&gt; _s-.,1,NoOp(Dial failed due to ${DIALSTATUS})</p>
<p>; Adds a dynamic agent/member to a Queue<br>; Prompts for call-back number - in not entered, uses CIDNum<br>[macro-agent-add]<br>exten =&gt; s,1,Wait(1)<br>exten =&gt; s,2,Macro(user-callerid)<br>exten =&gt; s,3,Read(CALLBACKNUM,agent-user)&nbsp; &nbsp;; get callback number from user
<br>exten =&gt; s,4,GotoIf($[&quot;${CALLBACKNUM}&quot; = &quot;&quot;]?5:7))&nbsp;; if user just pressed # or timed out, use cidnum<br>exten =&gt; s,5,Set(CALLBACKNUM=${CALLERID(number)})<br>exten =&gt; s,6,GotoIf($[&quot;${CALLBACKNUM}&quot; = &quot;&quot;]?2))&nbsp;; if still no number, start over
<br>exten =&gt; s,7,GotoIf($[&quot;${ARG2}&quot; = &quot;&quot;]?9:8))&nbsp;; arg2 is queue password<br>exten =&gt; s,8,Authenticate(${ARG2})<br>exten =&gt; s,9,AddQueueMember(<a href="mailto:${ARG1}|Local/${CALLBACKNUM}@from-internal/n">
${ARG1}|Local/${CALLBACKNUM}@from-internal/n</a>)&nbsp;; using chan_local allows us to have agents over trunks<br>exten =&gt; s,10,UserEvent(Agentlogin|Agent: ${CALLBACKNUM})<br>exten =&gt; s,11,Wait(1)<br>exten =&gt; s,12,Playback(agent-loginok)
<br>exten =&gt; s,13,Hangup()</p>
<p>; Removes a dynamic agent/member from a Queue<br>; Prompts for call-back number - in not entered, uses CIDNum<br>[macro-agent-del]<br>exten =&gt; s,1,Wait(1)<br>exten =&gt; s,2,Macro(user-callerid)<br>exten =&gt; s,3,Read(CALLBACKNUM,agent-user)&nbsp; &nbsp;; get callback number from user
<br>exten =&gt; s,4,GotoIf($[&quot;${CALLBACKNUM}&quot; = &quot;&quot;]?5:7))&nbsp;; if user just pressed # or timed out, use cidnum<br>exten =&gt; s,5,Set(CALLBACKNUM=${CALLERID(number)})<br>exten =&gt; s,6,GotoIf($[&quot;${CALLBACKNUM}&quot; = &quot;&quot;]?2))&nbsp;; if still no number, start over
<br>exten =&gt; s,7,RemoveQueueMember(<a href="mailto:${ARG1}|Local/${CALLBACKNUM}@from-internal/n">${ARG1}|Local/${CALLBACKNUM}@from-internal/n</a>)<br>exten =&gt; s,8,UserEvent(RefreshQueue)<br>exten =&gt; s,9,Wait(1)<br>
exten =&gt; s,10,Playback(agent-loggedoff)<br>exten =&gt; s,11,Hangup()</p>
<p>; arg1 = trunk number, arg2 = number<br>[macro-dialout-enum]<br>; This has been violently beaten upon by Rob Thomas, <a href="mailto:xrobau@gmail.com">xrobau@gmail.com</a><br>; to 1: Be compliant with all the depreciated bits in asterisk 
1.2 and<br>; above, and 2: to give a good shot at attempting to be compliant with<br>; RFC3761 by honouring the order in which records are returned.<br>exten =&gt; s,1,Macro(user-callerid)<br>exten =&gt; s,n,Macro(record-enable,${CALLERID(number)},OUT)
<br>exten =&gt; s,n,Macro(outbound-callerid,${ARG1})<br>exten =&gt; s,n,Set(GROUP()=OUT_${ARG1})<br>exten =&gt; s,n,GotoIf($[ ${GROUP_COUNT()} &gt; ${OUTMAXCHANS_${ARG1} ]?nochans)<br>exten =&gt; s,n,Set(DIAL_NUMBER=${ARG2})
<br>exten =&gt; s,n,Set(DIAL_TRUNK=${ARG1})<br>exten =&gt; s,n,AGI(fixlocalprefix)&nbsp; ; this sets DIAL_NUMBER to the proper dial string for this trunk<br>exten =&gt; s,n,GotoIf($[&quot;${DIAL_NUMBER:0:1}&quot; = &quot;+&quot;]?hasplus) ; Skip next line if it already is prefixed by a plus
<br>exten =&gt; s,n,Set(DIAL_NUMBER=+${DIAL_NUMBER}) ; Add a plus to the start, becasue ENUMLOOKUP needs it.<br>; OK, this is now quite complex. To remain compliant, we have to iterate<br>; through, in order, the returned records. Since we want to make this 
<br>; call over the network, we can ignore tel: lines. Even if it&#39;s first<br>; priority. <br>exten =&gt; s,n(hasplus),Set(ENUMCOUNT=${ENUMLOOKUP(${DIAL_NUMBER},ALL,c,<a href="http://e164.org">e164.org</a>)})&nbsp; ;&nbsp; Should 
<a href="http://e164.org">e164.org</a> be a var? I think so.<br>; Now the count may be zero, so if it is, just go to failed<br>exten =&gt; s,n,GotoIf($[ $[ ${ENUMCOUNT} = 0 ] | $[x${ENUMCOUNT} = x ] ]?failed)<br>; Now, let&#39;s start through them.
<br>exten =&gt; s,n,Set(ENUMPTR=1)<br>exten =&gt; s,n(startloop),Set(ENUM=${ENUMLOOKUP(${DIAL_NUMBER},ALL,${ENUMPTR},<a href="http://e164.org">e164.org</a>)})<br>; Sanity check the return, make sure there&#39;s something in there.
<br>exten =&gt; s,n,GotoIf($[${LEN(${ENUM})} = 0 ]?continue)<br>exten =&gt; s,n,GotoIf($[&quot;${ENUM:0:3}&quot; = &quot;sip&quot; ]?sipuri)<br>exten =&gt; s,n,GotoIf($[&quot;${ENUM:0:3}&quot; = &quot;iax&quot; ]?iaxuri)<br>
; It doesn&#39;t matter if you don&#39;t have h323 enabled, as when it tries to dial, it cares<br>; about dialstatus and retries if there are any enum results left.<br>exten =&gt; s,n,GotoIf($[&quot;${ENUM:0:3}&quot; = &quot;h32&quot; ]?h323uri)
<br>; If we&#39;re here, it&#39;s not a protocol we know about. Let&#39;s increment the pointer<br>; and if it&#39;s more than ENUMCOUNT, we know we&#39;ve run out of options. We also can<br>; come here if the enum string we&#39;ve received is empty, or if the Dial command
<br>; returned CONGESTION or CHANUNAVAIL.<br>exten =&gt; s,n(continue),Set(ENUMPTR=$[${ENUMPTR}+1])<br>exten =&gt; s,n,GotoIf($[${ENUMPTR} &gt; ${ENUMCOUNT}]?failed)<br>; OK. If we&#39;re here, we&#39;ve still got some enum entries to go through. Back to 
<br>; the start with you!<br>exten =&gt; s,n,Goto(startloop)<br>; If the prefix is &#39;sip:&#39;...<br>exten =&gt; s,n(sipuri),Set(DIALSTR=SIP/${ENUM:4})<br>exten =&gt; s,n,Goto(dodial)<br>; If it&#39;s IAX2...<br>exten =&gt; s,n(iaxuri),Set(DIALSTR=IAX2/${ENUM:5})
<br>exten =&gt; s,n,Goto(dodial)<br>; Or even if it&#39;s H323.<br>exten =&gt; s,n(h323uri),Set(DIALSTR=H323/${ENUM:5})</p>
<p>exten =&gt; s,n(dodial),Dial(${DIALSTR})<br>exten =&gt; s,n,NoOp(Dial exited in macro-enum-dialout with ${DIALSTATUS})<br>; Now, if we&#39;re still here, that means the Dial failed for some reason. <br>; If it&#39;s CONGESTION or CHANUNAVAIL we probably want to try again on a
<br>; different channel. However, if it&#39;s the last one, we don&#39;t have any<br>; left, and I didn&#39;t keep any previous dialstatuses, so hopefully <br>; someone looking throught the logs would have seen the NoOp&#39;s
<br>exten =&gt; s,n,GotoIf($[&quot;${ENUMPTR}&quot; = &quot;${ENUMCOUNT}&quot;]?noneleft)<br>exten =&gt; s,n,GotoIf($[ $[ &quot;${DIALSTATUS}&quot; = &quot;CHANUNAVAIL&quot; ] | $[ &quot;${DIALSTATUS}&quot; = &quot;CONGESTION&quot; ] ]?continue)
<br>; If we&#39;re here, then it&#39;s BUSY or NOANSWER or something and well, deal with it.<br>exten =&gt; s,n(noneleft),Goto(s-${DIALSTATUS},1)<br>; Here are the exit points for the macro.<br>exten =&gt; s,n(failed),NoOp(EnumLookup failed)
<br>exten =&gt; s,n,Goto(end)<br>exten =&gt; s,n(nochans),NoOp(max channels used up)<br>exten =&gt; s,n(end),NoOp(Exiting macro-dialout-enum)</p>
<p>exten =&gt; s-BUSY,1,NoOp(Trunk is reporting BUSY)<br>exten =&gt; s-BUSY,2,Busy()<br>exten =&gt; s-BUSY,3,Wait(60)<br>exten =&gt; s-BUSY,4,NoOp()</p>
<p>exten =&gt; _s-.,1,NoOp(Dial failed due to ${DIALSTATUS})</p>
<p>[macro-record-enable]<br>exten =&gt; s,1,GotoIf(${LEN(${BLINDTRANSFER})} &gt; 0?2:4)<br>exten =&gt; s,2,ResetCDR(w)<br>exten =&gt; s,3,StopMonitor()<br>exten =&gt; s,4,AGI(recordingcheck,${TIMESTAMP},${UNIQUEID})<br>exten =&gt; s,5,Noop(No recording needed) 
<br>exten =&gt; s,999,Monitor(wav49,${CALLFILENAME}, mb)</p>
<p>;exten =&gt; s,3,BackGround(for-quality-purposes)<br>;exten =&gt; s,4,BackGround(this-call-may-be)<br>;exten =&gt; s,5,BackGround(recorded)</p>
<p>; This macro is for dev purposes and just dumps channel/app variables.&nbsp; Useful when designing new contexts. <br>[macro-dumpvars]<br>exten =&gt; s,1,Noop(ACCOUNTCODE=${ACCOUNTCODE})<br>exten =&gt; s,2,Noop(ANSWEREDTIME=${ANSWEREDTIME})
<br>exten =&gt; s,3,Noop(BLINDTRANSFER=${BLINDTRANSFER})<br>exten =&gt; s,4,Noop(CALLERID=${CALLERID(all)})<br>exten =&gt; s,5,Noop(CALLERID(name)=${CALLERID(name)})<br>exten =&gt; s,6,Noop(CALLERID(number)=${CALLERID(number)})
<br>exten =&gt; s,7,Noop(CALLINGPRES=${CALLINGPRES})<br>exten =&gt; s,8,Noop(CHANNEL=${CHANNEL})<br>exten =&gt; s,9,Noop(CONTEXT=${CONTEXT})<br>exten =&gt; s,10,Noop(DATETIME=${DATETIME})<br>exten =&gt; s,11,Noop(DIALEDPEERNAME=${DIALEDPEERNAME})
<br>exten =&gt; s,12,Noop(DIALEDPEERNUMBER=${DIALEDPEERNUMBER})<br>exten =&gt; s,13,Noop(DIALEDTIME=${DIALEDTIME})<br>exten =&gt; s,14,Noop(DIALSTATUS=${DIALSTATUS})<br>exten =&gt; s,15,Noop(DNID=${DNID})<br>exten =&gt; s,16,Noop(EPOCH=${EPOCH})
<br>exten =&gt; s,17,Noop(EXTEN=${EXTEN})<br>exten =&gt; s,18,Noop(HANGUPCAUSE=${HANGUPCAUSE})<br>exten =&gt; s,19,Noop(INVALID_EXTEN=${INVALID_EXTEN})<br>exten =&gt; s,20,Noop(LANGUAGE=${LANGUAGE})<br>exten =&gt; s,21,Noop(MEETMESECS=${MEETMESECS})
<br>exten =&gt; s,22,Noop(PRIORITY=${PRIORITY})<br>exten =&gt; s,23,Noop(RDNIS=${RDNIS})<br>exten =&gt; s,24,Noop(SIPDOMAIN=${SIPDOMAIN})<br>exten =&gt; s,25,Noop(SIP_CODEC=${SIP_CODEC})<br>exten =&gt; s,26,Noop(SIPCALLID=${SIPCALLID})
<br>exten =&gt; s,27,Noop(SIPUSERAGENT=${SIPUSERAGENT})<br>exten =&gt; s,28,Noop(TIMESTAMP=${TIMESTAMP})<br>exten =&gt; s,29,Noop(TXTCIDNAME=${TXTCIDNAME})<br>exten =&gt; s,30,Noop(UNIQUEID=${UNIQUEID})<br>exten =&gt; s,31,Noop(TOUCH_MONITOR=${TOUCH_MONITOR})
<br>exten =&gt; s,32,Noop(MACRO_CONTEXT=${MACRO_CONTEXT})<br>exten =&gt; s,33,Noop(MACRO_EXTEN=${MACRO_EXTEN})<br>exten =&gt; s,34,Noop(MACRO_PRIORITY=${MACRO_PRIORITY})</p>
<p>[macro-user-logon]<br>; check device type<br>exten =&gt; s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})<br>exten =&gt; s,2,GotoIf($[&quot;${DEVICETYPE}&quot; = &quot;fixed&quot;]?s-FIXED,1)<br>; get user&#39;s extension
<br>exten =&gt; s,3,Set(AMPUSER=${ARG1})<br>exten =&gt; s,4,GotoIf($[&quot;${AMPUSER}&quot; = &quot;&quot;]?5:9)<br>exten =&gt; s,5,BackGround(please-enter-your)<br>exten =&gt; s,6,Playback(extension)<br>exten =&gt; s,7,Read(AMPUSER,then-press-pound)
<br>; get user&#39;s password and authenticate<br>exten =&gt; s,8,Wait(1)<br>exten =&gt; s,9,Set(AMPUSERPASS=${DB(AMPUSER/${AMPUSER}/password)})<br>exten =&gt; s,10,GotoIf($[${LEN(${AMPUSERPASS})} = 0]?s-NOPASSWORD,1)<br>
; do not continue if the user has already logged onto this device<br>exten =&gt; s,11,Set(DEVICEUSER=${DB(DEVICE/${CALLERID(number)}/user)})<br>exten =&gt; s,12,GotoIf($[&quot;${DEVICEUSER}&quot; = &quot;${AMPUSER}&quot;]?s-ALREADYLOGGEDON,1)
<br>exten =&gt; s,13,Authenticate(${AMPUSERPASS})<br>; devices can only be mapped to one user - loggoff anyone else who is here<br>exten =&gt; s,14,Macro(user-logoff)<br>; map user to device<br>exten =&gt; s,15,Set(AMPUSERDEVICES=${DB(AMPUSER/${AMPUSER}/device)})
<br>exten =&gt; s,16,GotoIf($[${LEN(${AMPUSERDEVICES})} = 0]?18) <br>exten =&gt; s,17,Set(AMPUSERDEVICES=${AMPUSERDEVICES}&amp;)<br>exten =&gt; s,18,Set(AMPUSERDEVICES=${AMPUSERDEVICES}${CALLERID(number)})<br>exten =&gt; s,19,Set(DB(AMPUSER/${AMPUSER}/device)=${AMPUSERDEVICES})
<br>; map device to user<br>exten =&gt; s,20,Set(DB(DEVICE/${CALLERID(number)}/user)=${AMPUSER})<br>; create symlink from dummy device mailbox to user&#39;s mailbox<br>exten =&gt; s,21,System(/bin/ln -s /var/spool/asterisk/voicemail/default/${AMPUSER}/ /var/spool/asterisk/voicemail/device/${CALLERID(number)})
</p>
<p>exten =&gt; s-FIXED,1,NoOp(Device is FIXED and cannot be logged into)<br>exten =&gt; s-FIXED,2,Playback(ha/phone)<br>exten =&gt; s-FIXED,3,SayDigits(${CALLERID(number)})<br>exten =&gt; s-FIXED,4,Playback(is-curntly-unavail)
<br>exten =&gt; s-FIXED,5,Playback(vm-goodbye)<br>exten =&gt; s-FIXED,6,Hangup ;TODO should play msg indicated device cannot be logged into </p>
<p>exten =&gt; s-ALREADYLOGGEDON,1,NoOp(This device has already been logged into by this user)<br>exten =&gt; s-ALREADYLOGGEDON,2,Playback(vm-goodbye)<br>exten =&gt; s-ALREADYLOGGEDON,3,Hangup ;TODO should play msg indicated device is already logged into 
</p>
<p>exten =&gt; s-NOPASSWORD,1,NoOp(This extension does not exist or no password is set)<br>exten =&gt; s-NOPASSWORD,2,Playback(an-error-has-occured)<br>exten =&gt; s-NOPASSWORD,3,Playback(vm-goodbye)<br>exten =&gt; s-NOPASSWORD,4,Hangup ;TODO should play msg indicated device is already logged into 
</p>
<p>[macro-user-logoff]<br>; check device type<br>exten =&gt; s,1,Set(DEVICETYPE=${DB(DEVICE/${CALLERID(number)}/type)})<br>exten =&gt; s,2,GotoIf($[&quot;${DEVICETYPE}&quot; = &quot;fixed&quot;]?s-FIXED,1)<br>; remove entry from user&#39;s DEVICE key
<br>; delete the symlink to user&#39;s voicemail box<br>exten =&gt; s,3,System(rm -f /var/spool/asterisk/voicemail/device/${CALLERID(number)})<br>exten =&gt; s,4,Set(DEVAMPUSER=${DB(DEVICE/${CALLERID(number)}/user)})<br>exten =&gt; s,5,Set(AMPUSERDEVICES=${DB(AMPUSER/${DEVAMPUSER}/device)})
<br>exten =&gt; s,6,AGI(list-item-remove.php,${AMPUSERDEVICES},${CALLERID(number)},AMPUSERDEVICES,&amp;)<br>; reset user -&gt; device mapping<br>; users can log onto multiple devices, need to just remove device from value
<br>exten =&gt; s,7,Set(DB(AMPUSER/${DEVAMPUSER}/device)=${AMPUSERDEVICES})<br>; reset device -&gt; user mapping<br>exten =&gt; s,8,Set(DB(DEVICE/${CALLERID(number)}/user)=none)<br>exten =&gt; s,9,Playback(vm-goodbye)</p>

<p>exten =&gt; s-FIXED,1,NoOp(Device is FIXED and cannot be logged out of)<br>exten =&gt; s-FIXED,2,Playback(an-error-has-occured)<br>exten =&gt; s-FIXED,3,Playback(vm-goodbye)<br>exten =&gt; s-FIXED,4,Hangup ;TODO should play msg indicated device cannot be logged into 
</p>
<p>;sets the callerid of the device to that of the logged in user<br>[macro-user-callerid]<br>exten =&gt; s,1,Set(AMPUSER=${DB(DEVICE/${CALLERID(number)}/user)})<br>exten =&gt; s,2,Set(EMERGENCYCID=${DB(DEVICE/${CALLERID(number)}/emergency_cid)})
<br>exten =&gt; s,3,Set(AMPUSERCIDNAME=${DB(AMPUSER/${AMPUSER}/cidname)})<br>exten =&gt; s,4,GotoIf($[&quot;${AMPUSERCIDNAME}&quot; = &quot;&quot;]?6) <br>exten =&gt; s,5,Set(CALLERID(all)=\&quot;${AMPUSERCIDNAME}\&quot; &lt;${AMPUSER}&gt;)
<br>exten =&gt; s,6,NoOp(Using CallerID ${CALLERID(all)})</p>
<p>; overrides callerid out trunks<br>; arg1 is trunk<br>; macro-user-callerid should be called _before_ using this macro<br>[macro-outbound-callerid]<br>exten =&gt; s,1,Set(USEROUTCID=${DB(AMPUSER/${CALLERID(number)}/outboundcid)})
<br>exten =&gt; s,2,GotoIf($[&quot;${OUTCID_${ARG1}:1:2}&quot; = &quot;&quot;]?4)&nbsp; ;check for CID override for trunk (global var)<br>exten =&gt; s,3,Set(CALLERID(all)=${OUTCID_${ARG1}})<br>exten =&gt; s,4,GotoIf($[&quot;${USEROUTCID:1:2}&quot; = &quot;&quot;]?6) ; check CID override for extension
<br>exten =&gt; s,5,Set(CALLERID(all)=${USEROUTCID})<br>exten =&gt; s,6,GotoIf($[&quot;${EMERGENCYROUTE:1:2}&quot; = &quot;&quot;]?8) ; check EMERGENCYROUTE override (set by route)<br>exten =&gt; s,7,Set(CALLERID(all)=${EMERGENCYCID}) ; emergency cid for device
<br>exten =&gt; s,8,NoOp(CallerID set to ${CALLERID(all)})</p>
<p>&nbsp;</p>
<p>; ############################################################################<br>; Applications [app]<br>; ############################################################################<br>; Moved to external file applications.conf
</p>
<p>#include applications.conf</p>
<p><br>;<br>; ############################################################################<br>; Inbound Contexts [from]<br>; ############################################################################</p>
<p>[from-sip-external]</p>
<p>;give external sip users congestion and hangup<br>exten =&gt; _.,1,Set(TIMEOUT(absolute)=15)<br>exten =&gt; _.,2,Congestion <br>exten =&gt; _.,3,Hangup</p>
<p>[from-internal]<br>;allow phones to use applications<br>include =&gt; app-userlogonoff<br>include =&gt; app-directory<br>include =&gt; app-dnd<br>include =&gt; app-callforward<br>include =&gt; app-callwaiting<br>include =&gt; app-messagecenter
<br>include =&gt; app-calltrace<br>include =&gt; parkedcalls<br>include =&gt; from-internal-custom<br>;allow phones to dial other extensions<br>include =&gt; ext-fax<br>include =&gt; ext-zapbarge<br>include =&gt; ext-record
<br>include =&gt; ext-test<br>;allow phones to access generated contexts<br>include =&gt; from-internal-additional<br>exten =&gt; s,1,Macro(hangupcall)<br>exten =&gt; h,1,Macro(hangupcall)</p>
<p>; ############################################################################<br>; Extension Contexts [ext]<br>; ############################################################################</p>
<p>[ext-zapbarge]<br>exten =&gt; 888,1,Macro(user-callerid)<br>exten =&gt; 888,2,Set(GROUP()=${CALLERID(number)})<br>exten =&gt; 888,3,Answer<br>exten =&gt; 888,4,Wait(1)<br>exten =&gt; 888,5,ZapBarge<br>exten =&gt; 888,6,Hangup
</p>
<p>[ext-fax]<br>exten =&gt; s,1,Answer<br>exten =&gt; s,2,Goto(in_fax,1)<br>exten =&gt; in_fax,1,GotoIf($[&quot;${FAX_RX}&quot; = &quot;system&quot;]?2:analog_fax,1)<br>exten =&gt; in_fax,2,Macro(faxreceive)<br>exten =&gt; in_fax,3,system(tiff2ps -2eaz -w 
8.5 -h 11 ${FAXFILE} | ps2pdf - ${FAXFILE}.pdf)<br>exten =&gt; in_fax,4,system(mime-construct --to ${EMAILADDR} --subject &quot;Fax from ${CALLERID(number)} ${CALLERID(name)}&quot; --attachment ${CALLERID(number)}.pdf --type application/pdf --file ${FAXFILE}.pdf)
<br>exten =&gt; in_fax,5,system(rm ${FAXFILE} ${FAXFILE}.pdf)<br>exten =&gt; in_fax,6,Hangup<br>exten =&gt; analog_fax,1,GotoIf($[&quot;${FAX_RX}&quot; = &quot;disabled&quot;]?3:2)&nbsp; ;if fax is disabled, just hang up<br>exten =&gt; analog_fax,2,Set(DIAL=${DB(DEVICE/${FAX_RX}/dial)});
<br>exten =&gt; analog_fax,3,Dial(${DIAL},20,d)<br>exten =&gt; analog_fax,4,Hangup<br>;exten =&gt; out_fax,1,wait(7)<br>exten =&gt; out_fax,1,txfax(${TXFAX_NAME}|caller)<br>exten =&gt; out_fax,2,Hangup<br>exten =&gt; h,1,Hangup()
</p>
<p>[ext-record]<br>exten =&gt; *77,1,Macro(user-callerid)<br>exten =&gt; *77,2,Wait(2)<br>exten =&gt; *77,3,Record(${CALLERID(number)}-ivrrecording:wav) <br>exten =&gt; *77,4,Wait(2)<br>exten =&gt; *77,5,Hangup<br>exten =&gt; *99,1,Macro(user-callerid)
<br>exten =&gt; *99,2,Playback(${CALLERID(number)}-ivrrecording) <br>exten =&gt; *99,3,Wait(2) <br>exten =&gt; *99,4,Hangup </p>
<p>;this is where parked calls go if they time-out.&nbsp; Should probably re-ring<br>[default]<br>include =&gt; ext-local<br>exten =&gt; s,1,Playback(vm-goodbye)<br>exten =&gt; s,2,Macro(hangupcall)</p>
<p>[ext-test]<br>exten =&gt; 7777,1,Goto(from-pstn,s,1)<br>exten =&gt; 666,1,Goto(ext-fax,in_fax,1)<br>exten =&gt; h,1,Macro(hangupcall)</p>
<p>;echo test<br>;exten =&gt; *43,1,Answer<br>;exten =&gt; *43,2,Wait(2)<br>;exten =&gt; *43,3,Playback(demo-echotest)<br>;exten =&gt; *43,4,Echo<br>;exten =&gt; *43,5,Playback(demo-echodone)<br>;exten =&gt; *43,6,Hangup
<br></p></div>
<div><br>&nbsp;</div>