Using Asterisk As a Standalone Voicemail Server

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:

  1. If you are building a large, centralized system and have several servers each providing a specific function (proxy server, media gateway, voicemail, conferencing, etc.)

  2. If you wish to replace the voicemail system on a traditional PBX with an Asterisk voicemail

Asterisk can serve in either of these roles.

Integrating Asterisk into a SIP Environment As a Standalone Voicemail Server

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.

Figure 8.1. Simplified SIP enterprise environment

Simplified SIP enterprise environment

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

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.

Dialplan requirements

The dialplan of the voicemail server can be fairly simple. Two needs must be satisfied:

  1. Receive incoming calls and direct them to the appropriate mailbox

  2. Handle incoming calls from users wishing to check their messages

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]

Note

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

sip.conf requirements

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.

SMDI (Simplified Message Desk Interface)

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.