Dialplan Integration

There are two primary dialplan applications that are provided by the app_voicemail.so module in Asterisk. The first, simply named VoiceMail(), does exactly what you would expect it to, which is to record a message in a mailbox. The second one, VoiceMailMain(), allows a caller to log into a mailbox to retrieve messages.

The VoiceMail() Dialplan Application

When you want to pass a call to voicemail, you need to provide two arguments: the mailbox (or mailboxes) in which the message should be left, and any options relating to this, such as which greeting to play or whether to mark the message as urgent. The structure of the VoiceMail() command is this:

VoiceMail(mailbox[@context][&mailbox[@context][&...]][,options])

The options you can pass to VoiceMail() to provide a higher level of control are detailed in Table 8.4, “VoiceMail() optional arguments”.

Table 8.4. VoiceMail() optional arguments

ArgumentPurpose
bInstructs Asterisk to play the busy greeting for the mailbox (if no busy greeting is found, the unavailable greeting will be played).
d([c])Accepts digits to be processed by context c. If the context is not specified, it will default to the current context.
g(#)Applies the specified amount of gain (in decibels) to the recording. Only works on DAHDI channels.
sSuppresses playback of instructions to the callers after playing the greeting.
uInstructs Asterisk to play the unavailable greeting for the mailbox (this is the default behavior).
UIndicates that this message is to be marked as urgent. The most notable effect this has is when voicemail is stored on an IMAP server. In that case, the email will be marked as urgent. When the mailbox owner calls in to the Asterisk voicemail system, he should also be informed that the message is urgent.
PIndicates that this message is to be marked as priority.

The VoiceMail() application sends the caller to the specified mailbox, so that he can leave a message. The mailbox should be specified as mailbox@context, where context is the name of the voicemail context. The option letters b or u can be added to request the type of greeting. If the letter b is used, the caller will hear the mailbox owner’s busy message. If the letter u is used, the caller will hear the mailbox owner’s unavailable message (if one exists).

Consider this simple example extension 101, which allows people to call John:

exten => 101,1,Dial(${JOHN})

Let’s add an unavailable message that the caller will be played if John doesn’t answer the phone. Remember, the second argument to the Dial() application is a timeout. If the call is not answered before the timeout expires, the call is sent to the next priority. Let’s add a 10-second timeout, and a priority to send the caller to voicemail if John doesn’t answer in time:

exten => 101,1,Dial(${JOHN},10)
exten => 101,n,VoiceMail(101@default,u)      

Now, let’s change it so that if John is busy (on another call), the caller will be sent to his voicemail, where he will hear John’s busy message. To do this, we will make use of the ${DIALSTATUS} variable, which contains one of several status values (type core show application dial at the Asterisk console for a listing of all the possible values):

exten => 101,1,Dial(${JOHN},10)
   same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy:unavail)
   same => n(unavail),VoiceMail(101@default,u)
   same => n,Hangup()
   same => n(busy),VoiceMail(101@default,b)
   same => n,Hangup()

Now callers will get John’s voicemail (with the appropriate greeting) if John is either busy or unavailable. A slight problem remains, however, in that John has no way of retrieving his messages. We will remedy that in the next section.

The VoiceMailMain() Dialplan Application

Users can retrieve their voicemail messages, change their voicemail options, and record their voicemail greetings using the VoiceMailMain() application. VoiceMailMain() accepts two arguments: the mailbox number (and optionally the context) to be accessed, and some options. Both arguments are optional.

The structure of the VoiceMailMain() application looks like this:

VoiceMailMain([mailbox][@context][,options])

If you do not pass any arguments to VoiceMailMain(), it will play a prompt asking the caller to provide her mailbox number. The options that can be supplied are listed in Table 8.5, “VoiceMailMain() optional arguments”.

Table 8.5. VoiceMailMain() optional arguments

ArgumentPurpose
pAllows you to treat the <mailbox> parameter as a prefix to the mailbox number.
g(#)Increases the gain by # decibels when playing back messages.
sSkips the password check.
a(folder)Starts the session in one of the following voicemail folders (defaults to 0): 0 - INBOX, 1 - Old, 2 - Work, 3 - Family, 4 - Friends, 5 - Cust1, 6 - Cust2, 7 - Cust3, 8 - Cust4, 9 - Cust5

To allow users to dial an extension to check their voicemail, you could add an extension to the dialplan like this:

[Services]

exten => *98,1,VoiceMailMain()

Creating a Dial-by-Name Directory

One last feature of the Asterisk voicemail system that we should cover is the dial-by-name directory. This is created with the Directory() application. This application uses the names defined in the mailboxes in voicemail.conf to present the caller with a dial-by-name directory of the users.

Directory() takes up to three arguments: the voicemail context from which to read the names, the optional dialplan context in which to dial the user, and an option string (which is also optional). By default, Directory() searches for the user by last name, but passing the f option forces it to search by first name instead. Let’s add two dial-by-name directories to the incoming context of our sample dialplan, so that callers can search by either first or last name:

exten => 8,1,Directory(default,incoming,f)
exten => 9,1,Directory(default,incoming)

If callers press 8, they’ll get a directory by first name. If they dial 9, they’ll get the directory by last name.

Using a Jitterbuffer

When using Asterisk as a voicemail server,[86] you may want to add a jitterbuffer in between voicemail and the caller. The purpose of a jitterbuffer is to help deal with the fact that when a call traverses an IP network, the traffic may not arrive with perfect timing and in perfect order. If packets occasionally arrive with a bit of delay (jitter) or if they arrive out of order, a jitterbuffer can fix it so that the voicemail system receives the voice stream on time and in order. If the jitterbuffer detects that a packet was lost (or may arrive so late that it will no longer matter), it can perform packet loss concealment. That is, it will attempt to make up a frame of audio to put in place of the lost audio to make it harder to hear that audio was lost.

In Asterisk, jitterbuffer support can only be enabled on a bridge between two channels. In the case of voicemail, there is generally only a single channel connected to one of the voicemail applications. To enable the use of a jitterbuffer in front of voicemail, we create a bridge between two channels by using a Local channel and specifying the j option. Specifying the n option for the Local channel additionally ensures that the Local channel is not optimized out of the call path in Asterisk:

[Services]

exten => *98,1,Dial(Local/vmm@Services/nj)

exten => vmm,1,VoiceMailMain()


[86] This advice applies to any situation where Asterisk is the endpoint of a call. Another example would be when using the MeetMe() or ConfBridge() applications for conferencing.