In a traditional telecom environment, the voicemail server was typically a standalone unit (provided either as a separate server altogether, or as an add-in card to the system). Very few PBXs had fully integrated voicemail (in the sense that voicemail was an integral part of the PBX rather than a peripheral device).
Asterisk is quite capable of serving as a standalone voicemail system. The two most common reasons one might want to do this are:
Asterisk can serve in either of these roles.
If you want to have Asterisk act as a dedicated voicemail server (i.e., with no sets registered to it and no other types of calls passing through it), the process from the dialplan perspective is quite simple. Getting message waiting to work can be a bit more difficult, though.
Let’s start with a quick diagram. Figure 8.1, “Simplified SIP enterprise environment” shows an overly simplified example of a typical SIP enterprise environment. We don’t even have an Asterisk server in there (other than for the voicemail), in order to give you a generic representation of how Asterisk could serve as a standalone voicemail server in an otherwise non-Asterisk environment.
Unfortunately, Asterisk cannot send message notification to an endpoint if it doesn’t know where that endpoint is. In a typical Asterisk system, where set registration and voicemail are handled on the same machine, this is never a problem, since Asterisk knows where the sets are. But in an environment where the sets are not registered to Asterisk, this can become a complex problem.
There are several solutions on the
Internet that recommend using the externnotify
option in voicemail.conf
, triggering an external script
whenever a message is left in a mailbox (or deleted). While we can’t say
that’s a bad approach, we find it a bit kludgy, and it requires the
administrator to understand how to write an external script or program
to handle the actual passing of the message.
Instead you can statically define an entry
for each mailbox in the voicemail server’s sip.conf
file, indicating where the message notifications are to
be sent. Rather than defining the address of each endpoint, however, you
can have the voicemail server send all messages to the proxy, which will
handle the relay of the message notifications to the appropriate
endpoints.
The voicemail server still needs to know
about the SIP endpoints, even though the devices are not registered
directly to it. This can be done either through a sip.conf
file that identifies each SIP
endpoint, or through a static real-time database that does the same
thing. Whether you use sip.conf
or
the Asterisk Realtime Architecture (ARA), each endpoint will require an
entry similar to this:
[messagewaiting](!) ; a template to handle the settings common ; to all mailboxes type=peer subscribecontext=voicemailbox ; the dialplan context on the voicemail server context=voicemailbox ; the dialplan context on the voicemail server host=192.168.1.1 ; ip address of presence server [0000FFFF0001](messagewaiting) ; this will need to match the subscriber ; name on the proxy mailbox=0000FFFF0001@DIR1 ; this has to be in the form mailbox@mailboxcontext defaultuser=0000FFFF0001 ; this will need to match the subscriber ; name on the proxy
Note that Asterisk’s dynamic realtime will not work with this configuration, as a peer’s information is only loaded into memory when there is an actual call involving that peer. Since message notification is not a call as far as Asterisk is concerned, using dynamic realtime will not allow message waiting to happen for any peers not registered to Asterisk.
You will not want to implement this unless you have prototyped the basic operation of the solution. Although we all agree that SIP is a protocol, not everyone agrees as to the correct way to implement the protocol. As a result, there are many interoperability challenges that need to be addressed in a solution like this. We have provided a basic introduction to this concept in this book, but the implementation details will depend on other factors external to Asterisk, such as the capabilities of the proxy.
The fact that no device has to register with Asterisk will significantly reduce the load on the Asterisk server, and as a result this design should allow for a voicemail server that can support several thousand subscribers.
The dialplan of the voicemail server can be fairly simple. Two needs must be satisfied:
The system that is passing calls to the
voicemail server should set some SIP headers in order to pass
additional information to the voicemail server. Typically, this
information would include the mailbox/username that is relevant to the
call. In our example, we are going to set the headers X-Voicemail-Mailbox
and X-Voicemail-Context
, which will contain information we wish to pass to the
voicemail server.[88]
If the source system is also an
Asterisk system, you might set the headers using the SIPAddHeader()
voicemail
application, in a manner similar to
this:
exten => sendtovoicemail,1,Verbose(2,Set SIP headers for voicemail) same => n,SipAddHeader(X-Voicemail-Mailbox: <mailbox number>) same => n,SipAddHeader(X-Voicemail-Context: voicemailbox)
Note that this dialplan does not go on the voicemail server. It would only be useful if one of the other servers in your environment was also an Asterisk server. If you were using a different kind of server, you would need to find out how to set custom headers in that platform, or find out if it already uses specific headers for this sort of thing, and possibly modify the dialplan on the voicemail server to handle those headers.
The voicemail server will need an
extensions.conf
file containing
the following:
[voicemailbox] ; direct incoming calls to a mailbox exten => Deliver,1,NoOp() same => n,Set(Mailbox=${SIP_HEADER(X-Voicemail-Mailbox)}) same => n,Set(MailboxContext=${SIP_HEADER(X-Voicemail-Context)}) same => n,VoiceMail(${Mailbox}@${MailboxContext}) same => n,Hangup() ; connect users to their mailbox so that they can retrieve messages exten => Retrieve,1,NoOp() same => n,Set(Mailbox=${SIP_HEADER(X-Voicemail-Mailbox)}) same => n,Set(MailboxContext=${SIP_HEADER(X-Voicemail-Context)}) same => n,VoiceMailMain(${Mailbox}@${MailboxContext}) same => n,Hangup()
In the sip.conf
file on the voicemail server, not
only are entries required for all the mailboxes for message waiting
notification, but some sort of entry is required to define the
connection between the voicemail server and the rest of the SIP
environment:
[VOICEMAILTRUNK]
type=peer
defaultuser=voicemail
fromuser=voicemail
secret=s0m3th1ngs3cur3
canreinvite=no
host=<address of proxy/registrar server
>
disallow=all
allow=ulaw
dtmfmode=rfc2833
context=voicemailbox
The other end of the connection (probably your proxy server) must be configured to pass voicemail connections to the voicemail server.
Running Asterisk as a standalone voicemail server requires some knowledge of clustering and integration, but you can’t beat the price.
The Simplified Message Desk Interface (SMDI) protocol is intended to allow communication of basic message information between telephone systems and voicemail systems.
Asterisk supports SMDI, but given that this is an old protocol that runs across a serial connection, there are likely to be integration challenges. Support in various PBXs and other devices may be spotty. Still, it’s a fairly simple protocol, so for sure it’s worth testing out if you are considering using Asterisk as a voicemail replacement.
The following is not a detailed explanation of how to configure SMDI for Asterisk, but rather an introduction to the concepts, with some basic examples. If you are planning on implementing SMDI, you will need to write some complex dialplan logic and have a good understanding of how to interconnect systems via serial connections.
SMDI is enabled in Asterisk by the use of
two options in the [general]
section
of the voicemail.conf
file:
smdienable=yes smdiport=/dev/ttyS0; or whatever serial port you are connecting your SMDI service to
Additionally,
you will need an smdi.conf
file in
your /etc/asterisk
folder to define
the details of your SMDI configuration. It should look something like
this (see the smdi.conf.sample
file
for more information on the available options):
[interfaces] charsize=7 paritybit=even baudrate=1200 ; hopefully a higher bitrate is supported smdiport=/dev/ttyS0 ; or whatever serial port you'll be using to handle ; SMDI messages on asterisk [mailboxes] ; map incoming digit strings (typically DID numbers) ; to a valid mailbox@context in voicemail.conf smdiport=/dev/ttyS0 ; first declare which SMDI port the following mailboxes ; will use 4169671111=1234@default 4165551212=9999@default
In the dialplan there are two functions that will be wanted in an
SMDI configuration. The SMDI_MSG_RETRIEVE()
function pulls the
relevant message from the SMDI message queue. You need to pass the
function a search key (typically the DID that is referred to in the
message), and it will pass back an ID number that can be referenced by
the SMDI_MSG()
function:
SMDI_MSG_RETRIEVE(<smdi port
>,<search key
>[,timeout
[,options
]])
Once you have the SMDI message ID, you can
use the SMDI_MSG()
function
to access various details about the message, such as the
station
, callerID
, and type
(the SMDI message type):
SMDI_MSG(<message_id
>,<component
>)
In your dialplan, you will need to handle
the lookup of the SMDI messages that come in, in order to ensure that
calls are handled correctly. For example, if an incoming call is
intended for delivery to a mailbox, the message type might be one of
B
(for busy) or N
(for unanswered calls). If, on the other
hand, the call is intended to go to VoiceMailMain()
because the caller wants to
retrieve his messages, the SMDI message type would be D
, and that would have to be
handled.
[88] As far as we know, there aren’t any specific SIP headers that are standardized for this sort of thing, so you should be able to name the headers whatever you want. We chose these header names simply because they make some sort of sense. You may find that other headers would suit your needs better.