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.
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
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.
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
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()
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.
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.