Skip to main content



mod_voicemail is a Dialplan Application that provides voicemail services via Diaplans. It lets you send calls to voicemail, which allows callers to leave messages for users and allows users to retrieve and manage any messages left by callers.

Click here to expand Table of Contents


voicemail,Voicemail,[check] [auth] <profile_name> <domain_name> [<id>]

Dialplan variables


Skips playback of greeting message when leaving messages. Variable is unset after voicemail application finishes.

If using a command to access voicemail, you can use the following to direct the playout of a custom greeting to the caller:

<action application="set" data="skip_greeting=true"/>
<action application="voicemail" data="default $${domain} $1"/>

However, if using bridge to get to voicemail, you need to use "export" instead of "set" to get the channel variable to the correct leg of the call

<action application="export" data="skip_greeting=true"/>
<action application="bridge" data="loopback/app=voicemail:default $${domain} $1"/>


Skips playback of instructions when leaving messages. Variable is unset after voicemail application finishes.

<action application="set" data="skip_instructions=true"/>
<action application="voicemail" data="default $${domain} $1"/>

However, if using bridge to get to voicemail, you need to use "export" instead of "set" to get the channel variable to the correct leg of the call

<action application="export" data="skip_greeting=true"/>
<action application="bridge" data="loopback/app=voicemail:default $${domain} $1"/>

For instance, in dialplan/default.xml under <extension name="Local_Extension">, you would modify the xml by:

<action application="export" data="skip_instructions=true"/>
<action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/>


Set's the dialplan for the voicemail callback. This channel variable will override the parameter 'callback_dialplan' in voicemail.conf.xml

<action application="set" data="voicemail_callback_dialplan=XML"/>


Set's the dialplan context for the voicemail callback. This channel variable will override the parameter 'callback_context' in voicemail.conf.xml

<action application="set" data=""/>

Controlling User Parameters & Variables

When the following parameters are set in the extension conf files located in (conf/directory/'extension'.xml or conf/directory/default/'extension'.xml), they set options for your voicemail users


When set to false this user will not have a voicemail box. This means busy and no answer calls will not forward to a voicemail box, nor will the user be able to log in to a voicemail box.



The parameter allows you to override the default extension or phone number spoken by the system in the voicemail greeting. This can also be set in the dialplan before calling the voicemail app.

This controls system greetings that read back a phone number, not user recorded greetings. To change to a different recorded greeting, use voicemail_greeting_number below.

Example setting the parameter in the user's directory entry. This example will say "8661234567" in the voicemail generic system greeting instead of the extension number 1004.

Parameter set in user directory entry

<!-- note use of dashes in parameter name -->
<user id="1004">
<param name="password" value="xyzzy"/>
<param name="vm-password" value="1234"/>
<param name="vm-alternate-greet-id" value="8661234567"/>
<variable name="toll_allow" value="domestic,local"/>
<variable name="user_context" value="default"/>
<variable name="effective_caller_id_number" value="703-591-1635"/>
<variable name="effective_caller_id_name" value="Frank Haynes"/>
<variable name="callgroup" value="tech_support"/>

Example setting the variable before trasferring to voicemail. This example will say "2024561000" in the voicemail greeting instead of the extension number, for example 1019.

Variable set in dialplan

dial the extension (1000-1019) for 30 seconds and go to voicemail if the
call fails (continue_on_fail=true), otherwise hang up after a successful
bridge (hangup_after_bridge=true)
<extension name="Local_Extension">
<condition field="destination_number" expression="^(10[01][0-9])$">
<action application="export" data="dialed_extension=$1"/>
<action application="set" data="ringback=${us-ring}"/>
<action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="set" data="call_timeout=30"/>
<action application="set" data="hangup_after_bridge=true"/>
<action application="set" data="continue_on_fail=true"/>
<action application="bridge" data="user/${dialed_extension}@${domain_name}"/>
<action application="answer"/>
<!-- Note the use of underscore_ between elements of the variable name -->
<action application="export" data="voicemail_alternate_greet_id=2024561000"/>
<action application="sleep" data="1000"/>
<action application="bridge" data="loopback/app=voicemail:default ${domain_name} ${dialed_extension}"/>


Selects the user-recorded greeting to play.

If using a command to access voicemail, you can use the following to direct the playout of a custom greeting to the caller:

<action application="set" data="voicemail_greeting_number=1"/>
<action application="voicemail" data="default $${domain} ${dialed_extension}"/>

However, if using bridge to get to voicemail, you need to use "export" instead of "set" to get the channel variable to the correct leg of the call

<action application="export" data="voicemail_greeting_number=1"/>
<action application="bridge" data="loopback/app=voicemail:default $${domain} ${dialed_extension}"/>

By default, either of the above would play the file in $${base_dir}/storage/voicemail/default/$${domain}/<user>/greeting_1.wav. However, this file is not created until the user has recorded a custom greeting in slot 1.

If you have defined voicemail_greeting_number in the user's XML directory entry and would like to follow that value then execute the set_user app before transferring to voicemail.


This allows the user to use the web vm

<param name="http-allowed-api" value="voicemail"/>


This will put a limit to the length of voicemail messages a user can store. If 0 or missing doesn't make any limitation. Default is no limitation.

The following example will limit the user's voicemail box to 30 seconds. When the limit exceed, The caller will hear "mailbox is full, please try your call again later, goodbye".

<param name="vm-disk-quota" value="30"/>


This is the user's email address, default: undefined.
(originally called email-addr. Use vm-mailto instead)

This is defined in the directory for the particular user as a param. Multiple email addresses can be defined using a comma-separated list.

<param name="vm-mailto" value="" />


This is the FROM address to send the email, default: undefined

This is defined in the directory for the particular user as a param.

<param name="vm-mailfrom" value="" />

in the voicemail template you can get this value using: ${voicemail_email_from}


The address you want notification messages sent to, default: same as vm-mailto.

This is defined in the directory for the particular user as a param.

<param name="vm-notify-mailto" value="" />


This is the user's configured voicemail PIN. This is additional to the voicemail password that the user can change in the voicemail system. If the value is set to "user-choose", then there is no configured password and only the user set password is used. Note that if you set the vm_password in the directory XML, any changes to the password from a phone are stored in the voicemail_prefs table. The module does not update the XML. The result is that there will be 2 passwords that can access the mail box, the one set in XML and the one that the user set from the phone.

This is defined in the directory for the particular user as a param.


<param name="vm-password" value="12345" />


This parameter allows you to avoid sending the voicemail password in plain text. This is the same as the user a1-hash (see [[XML_User_Directory_Guide]]). Set this parameter to the MD5 hash of "userid:domain_name:vm-password". Example:

<!-- The password has been left as a comment for example -->
<!-- <param name="vm-password" value="12345"/> -->
<!-- The MD5 hash of "" -->
<param name="vm-a1-hash" value="fd5184d9d36a2009c72e1571abf0493e" />


Setting to true will send all messages to vm-mailto address (attachment based on vm-attach-file param), default: false

This is defined in the directory for the particular user as a param.

<param name="vm-email-all-messages" value="true" />


Setting to true will send a notify email to vm-notify-mailto when a vm is left (never has attachment)
default: false

This is defined in the directory for the particular user as a param.

<param name="vm-notify-email-all-messages" value="true" />


Setting this variable will inject the message into the specified voicemail mailbox.
This is defined in the directory for the particular user as a variable.
Please note that the variable 'vm_cc' needs to be set as a channel variable before mod_voicemail is called. When set as a directory variable, it only becomes a channel variable when the UA is authenticated.

Dialplan Example (recommended):

<action application="set" data=""/>
<action application="voicemail" data="default 1000"/>
<!--If you want to cc the message to multiple users, use a comma separated list of users:-->
<action application="set" data=",,"/>

Directory Example:

<domain name="">
<user id="101">
<!--Note: for user directory you can use either vm_cc in variables or the vm-cc param-->
<param name="vm-cc" value=",," />
<variable name="vm_cc" value="" />
<!--If you want to cc the message to multiple users, use a comma separated list of users:-->
<variable name="vm_cc" value=",," />


Setting to false will delete the local copy of the voicemail file after transmission of the mail message. When set to true the voicemail file will be kept locally and set as New for the phone to retrieve.
default: true


<param name="vm-keep-local-after-email" value="false" />


Setting to true will attach the audio file to the main email
default: false

This is defined in the directory for the particular user as a param.


<param name="vm-attach-file" value="true" />


This Parameter determines the storage type (and email type) for voicemails received and can be set per user. In order to use MP3 you must have mod_shout installed and loaded. The default is 'wav'.


<param name="vm-message-ext" value="mp3"/>


Determines the storage type (and email type) for voicemails received and can be set per originating user or the Dial Plan. In order to use MP3 you must have mod_shout installed and loaded. The default is 'wav'. This may be set from the Dial Plan to override the file type. If this variable is set it overrides the vm-message-ext parameter.
When this variable is set on the originating user the specified file type will apply to the receiver of the message.


<variable name="vm_message_ext" value="mp3"/>


This disables instructions for how to leave a message, and instead just plays a beep.

<param name="vm-skip-instructions" value="true"/>


The notify email will use the same template as the main email unless you define the new profile
default: undefined

<param name="notify-template-file" value="other_template"/>


This parameter allows to force the storage directory for voicemail files received and can be set per user. By default, voicemail files are stored in 'BASE_DIR/storage/voicemail/DOMAIN_NAME/USER_ID'.

It can be set to a full path, or a path relative to the BASE_DIR (usually /usr/local/freeswitch or /opt/freeswitch for debian installs).


<param name="vm-storage-dir" value="/home/voicemail/"/>

(warning) Note: Most users either save voicemails locally, on a network file share directory or using a distribusted network file system, like glusterFS. You can also save the voicemails locally and transfer to different FreeSWITCH servers in any manner: scp, rsync, Borgbackup, sneakernet, etc.

Here's a users input on GlusterFS:

Essentially, gluster is a cluster distributed filesystem. It uses local storage on each 'server' node, and that can then
be mounted on clients. It's intended for high performance compute resources, but works quite nicely for freeswitch backend.

In my case, I have 4 servers accessing the cluster - 2 freeswitch nodes that are setup as an HA pair using keepalived
(article already in wiki for that), 2 web server front end nodes for a local custom UI.

On the backend, I have the three gluster nodes for file service (odd number to insure quorum) and 3 Percona XTraDB mysql
nodes also operating as a cluster.

Everything except the two freeswitch instances is running as a VM. The FS nodes are running on real hardware.

The key difference with NFS is that the filesystem itself is redundant - so you can take any one of those backend nodes
out of service and it isn't visible (except as a momentary hang) to the servers that have the filesystem mounted.


If this is set to true (default false) we assume the storage-dir is shared, organized by realm/domain, with uses other than voicemail, so we adopt a directory structure of:



<param name="vm-storage-dir-shared" value="true"/>


This is like vm-storage-dir but we append the user ID to the directory so if vm-domain-storage-dir is /var/lib/freeswitch/storage/, it will store VM in /var/lib/freeswitch/storage/


<param name="vm-domain-storage-dir" value="/var/lib/voicemail/"/>

Using Outside Programs to Send Voicemail to Email

There are times when you don't want or need an email server on your PBX. For these times it would be nice to be able to
use an outside program to send the email.

Below is a python script that does just that. Note that it will give deprecation warnings on later versions of Python so needs to be rewritten to used MIME in place of MimeWriter.

TODO: Fix indentation

Copyright (c) 2009, ChronosTelecom, LLC
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
import smtplib
import sys
import MimeWriter
import mimetools
import mimetypes
import os
import StringIO
import re
import shutil
import time
import os.path
from optparse import OptionParser
PORT = 587
attach = ""
# Write data to a file given the filename. Make a backup of the file FIRST!
def write_file(filename,data):
fh = ""
cur_time = time.time()
if not fh:
if not os.path.exists(filename):
fh = open(filename,'w')
#print "WARNING: %s exists! Moving it to %s.bak.%s" % (filename,filename,cur_time)
shutil.move(filename,"%s.bak.%s" % (filename,cur_time))
fh = open(filename,'w')

# send the mail
def send(sender,to,message,verbose=False):
smtp = smtplib.SMTP(SERVER, PORT)
if verbose:
smtp.sendmail(sender, to, message)

def mail(sender='', to='', subject='', text='', attachments=None, verbose=False):
sender: sender's email address
to: receipient email address
subject: subject line
text: Email message body main part.
attachments: list of files to attach
message = StringIO.StringIO()
writer = MimeWriter.MimeWriter(message)
writer.addheader('To', to)
writer.addheader('From', sender)
writer.addheader('Subject', subject)
writer.addheader('MIME-Version', '1.0')


# start with a text/plain part
part = writer.nextpart()
body = part.startbody('text/plain')
# now add the attachments
if attachments is not None:
for a in attachments:
filename = os.path.basename(a)
ctype, encoding = mimetypes.guess_type(a)
if ctype is None:
ctype = 'application/octet-stream'
encoding = 'base64'
elif ctype == 'text/plain':
encoding = 'quoted-printable'
encoding = 'base64'

part = writer.nextpart()
part.addheader('Content-Transfer-Encoding', encoding)
body = part.startbody("%s; name=%s" % (ctype, filename))
print filename
mimetools.encode(open(a, 'rb'), body, encoding)
# that's all folks

def validate_email(fromAddress):
email_addr = re.compile(r'(([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))')
return bool(

if __name__ == "__main__":
fromAddress = ""
to = ""
subject = ""
infile = ""
body = ""
translate = ""
tempfile = ""
usestdin = False
verbose = False
delete = False
log = False

parser = OptionParser()
parser.add_option('-f', dest='fromAddress', metavar='FROMADDRESS',help="The from address for the email")
parser.add_option('-t', dest='toAddress', metavar='TOADDRESS',help="The to address for the email")
parser.add_option('-s', dest='subject', metavar='SUBJECT',help="The subject for the email")
parser.add_option('-a', dest='attachment', metavar='ATTACHMENT',help="The file to attach to the email")
parser.add_option('-b', dest='body', metavar='BODY',help="The body of the email")
parser.add_option('-x', dest='translate', metavar='TRANSLATE',help="Translate the attachment using a translator program.\ntiff2pdf is the only supported option at this time.")
parser.add_option('-i', dest='use_stdin', action="store_true", default=False,help="Use standard in as the input for the email message.")
parser.add_option('-d', dest='delete', action="store_true", default=False,help="Delete the attachments when done processing.")
parser.add_option('-v', dest='verbose', action="store_true", default=False,help="Verbose output for debugging.")
parser.add_option('-l', dest='log', action="store_true", default=False,help="Log the message to a file stored in /tmp/sendemail.log")
(options, args) = parser.parse_args()
if options.fromAddress:
fromAddress = options.fromAddress
if not validate_email(fromAddress):
print "Invalid From email address. Please try again."
if options.toAddress:
to = options.toAddress
if not validate_email(to):
print "Invalid To email address. Please try again."
if options.subject: subject = options.subject
if options.attachment: infile = options.attachment
if options.body: body = options.body
if options.translate: translate = options.translate
if options.use_stdin: usestdin = options.use_stdin
if options.verbose: verbose = options.verbose
if options.delete: delete = options.delete
if options.log: log = options.log
if usestdin is True:
message = ""
attachment = infile
for line in sys.stdin:
message += line
to_field = re.compile(r'To: <(([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?))>')
to_match =
to = str(
if log:
if translate == 'tiff2pdf':
tempfile = "/tmp/%s.pdf" % os.path.basename(infile)
command = "tiff2pdf %s -o %s" % (infile, tempfile)
attachment = tempfile
attachment = infile

mail(sender=fromAddress, to=to, subject=subject, text=body, attachments=attach, verbose=verbose)

# delete our temporary file - it's up to the caller to delete the attachments, if they want
if tempfile:
if delete and attachment:

Make the following changes to /usr/local/freeswitch/autoload_configs/switch.conf.xml:

<param name="mailer-app" value="/usr/local/freeswitch/scripts/"/>
<param name="mailer-app-args" value="-i -d -f -t"/>

Send_mail setting

To enable email setting for voicemail, make sure the following two lines are configured correctly in switch.conf.xml

<param name="mailer-app" value="sendmail"/>
<param name="mailer-app-args" value="-t"/>

'''Note''' - On CentOS and possibly other OSs, `sendmail` isn't in the non-root PATH so you'll want to specify the entire path in the mailer-app value or modify your PATH prior to running FreeSWITCH.

Exim4 settings

There have been several reports of segfaults with Exim4 in combination with Debian and FreeSWITCH - so far no definite resolution has been posted - mostly citing the advice below - which does not help(See [ here],[ here] and [ here]).
A default installation of '''postfix''' instead of exim4 is a workaround, if you just quickly want to setup a mailer for FreeSWITCH on Debian --[[User:Peletiah|Peletiah]] 15:19, 1 June 2011 (UTC).

Using '''msmtp''' together with exim4 on the same host works and can be used as a workaround, see the notes below in a dedicated sub-section -- [[User:Miconda|miconda]] Sep 24, 2012.

As of April 22, 2013, a patch was applied to resolve the stack size setting for child processes, which is the primary cause of this issue. See [ here] for details.

VM to email notification can also use other MTAs such as Debian's default Exim4. For email notification basically mod_voicemail constructs an email message that is then passed to standard input of the application defined in the "mailer-app" param found in switch.conf.xml.

The MTA application then needs to be configured in a way so that the recipients of the message are obtained from the To:, Cc:, and Bcc: header lines of the message passed to it. This is achieved in Exim4 with the -t option.

However, FS also adds another argument with the To: address to the command defined in the parameters above, so that the final command would look like:

cat /tmp/mail.12336173682b88 | exim4 -t

If you have set:

<param name="mailer-app" value="exim4"/>
<param name="mailer-app-args" value="-t"/>

This is because as documented in O'Reilly Sendmail's book, some versions of Sendmail add argument addresses to those obtained from the headers and also as a good measure to send the To: address to applications that cannot parse the headers in the email msg.

Exim's default behavior however is that these extra addresses specify addresses to which the message is NOT to be delivered. So in the command line described above "" is the actual recipient of the email message, but exim's default behavior takes the argument from the command line and subtracts the "" email address from the To: headers of the actual message, leaving it with no recipients at all.

Exim can be made to add the argument instead of subtracting it by setting the option extract_addresses_remove_arguments false in it's config and then you can use:

<param name="mailer-app" value="exim4"/>
<param name="mailer-app-args" value="-t"/>

But if you do not want to go through the hassle of changing exim's configuration, then you could also overcome the "extra" argument using a script such as:

exec exim4 -t

And then pointing the mailer app to this script:

<param name="mailer-app" value="/usr/local/bin/"/>
<!-- <param name="mailer-app-args" value="-t"/> -->

If you're using the sysV init script from this wiki, the stack size is set to some low value (240) which can cause exim to segfault; add a line in your to increase this value (8192 works for me).

Using MSMTP for Local Relay to Exim4 on Debian

This is a possible workaround to make voicemail email notification work on Debian with Exim4 as main MTA.

MSMTP can be installed together with Exim4 on the same host and can be configured to do relay to local exim4 instance. In this way, Voicemail module can use MSMTP, but the public email relaying is taken care by Exim.

Installation of MSMTP on Debian is very simple:

apt-get install msmtp

Its configuration has to be stored in '''/etc/msmtprc'''. To relay to localhost SMTP server, just set its content to the next three lines:

account default
syslog LOG_MAIL

By default, exim4 accepts messages from localhost without user authentication (to allow running processes to send email alerts), so you don't need to change anything in exim4 configuration (unless you disabled that default option).

On FreeSwitch configuration side, edit switch.conf.xml to set sending emails with MSMTP:

<param name="mailer-app" value="msmtp"/>

Windows settings

Example setting in switch.conf.xml for sending email on windows.

<param name="mailer-app" value="msmtp"/>

Mail via PHP

Example setting in switch.conf.xml for sending email with PHP mailer. Make sure the path to php is correct for mailer-app.

<param name="mailer-app" value="/usr/bin/php /usr/local/www/freeswitch/mailer_app.php"/>
<param name="mailer-app-args" value=""/>

nullmailer settings is installed sometimes as a sendmail service. Make sure the following two lines are configured correctly in switch.conf.xml

<param name="mailer-app" value="sendmail"/>
<param name="mailer-app-args" value=""/>
<-- don't comment out the args line, leave it in with no value -->

If you don't take out the ''-t'' default argument, nullmailer will create duplicate emails.

sSMTP settings can be used as a null mailer and has the advantage over that it permits sending to mail hosts that require SSL/TLS and/or authentication. It also logs to /var/log/mail.log which is useful for debugging.

sSMTP uses the same sendmail command, ignoring some options and failing if others are specified. Within conf/autoload_configs//switch.conf.xml, you need to include:

<param name="mailer-app" value="sendmail"/>
<param name="mailer-app-args" value="-f"/>

Within /etc/ssmtp/ssmtp.conf, your mileage may vary, but to relay to a Postfix server using submission (tcp/587), the config looks like this:

root=postmaster # part of the default config
AuthPass=mypassword # This is useful if your FS box is not in DNS or has a different domain from the sending email
FromLineOverride=NO # This stops the mail message overriding the -f switch on the command line, useful if your FS ${domain} is an IP address

Google will help you get a config that matches your configuration.

Debugging an external mailer

FreeSWITCH does very little error reporting on emails. Basically, once the email is
accepted for queueing, FreeSWITCH has (rightly) lost interest. So, it is best to first test that mails can be sent from your FreeSWITCH box before trying to get FreeSWITCH to do it.

First, create a minimal email in a text file:

From: <>
To: <>
Date: Thu, 2 Feb 2012 13:13:40 +0100
Subject: Test 131340 (I always put a timestamp in the subject line when
testing email due to the queueing and routing and stuff)
Minimal test email 131340 (and I try to remember to put the same timestamp in the body of the text)

Then send it from the command line with:

cat email.txt | sendmail -f

Nearly all mailers have a 'sendmail' alias even if they are not sendmail itself. Depending on the local mail server you are using, you may have to include the -t switch which extracts the To address(es) from the message itself.

If this command fails, then you may not have sendmail, or a clone, installed. If you don't need the weight and features of sendmail, exim or postfix, leave them alone and use a simple null mailer like nullmailer or sSMTP as described above.

If the command works but the mail still does not reach the destination, then you know you have a mail transport issue and can solicit the assistance of your friendly postmaster or a forum appropriate to your operating system and mailer.

Once you are reliably sending email from the shell, transfer your settings into conf/autoload_configs/switch.conf.xml

For example, for sSMTP:

<param name="mailer-app" value="sendmail"/>
<param name="mailer-app-args" value="-f"/>

Note that if you need to run your mailer-app with no args, explicitly state them as <param name="mailer-app-args" value="" /> as the default if not specified is to use "-t".

With your external mailer known to be working, you can now narrow down your debugging to FreeSWITCH. Make sure that you include all the parameters required in the user directory entry. For example, in conf/directory/default/1001.xml:

<param name="vm-password" value="1001" />
<param name="vm-email-all-messages" value="true" />
<param name="vm-mailto" value="" />
<!-- or just notify -->
<param name="vm-notify-mailto" value="" />
<!-- don't need notify if you have the full voicemail -->
<param name="vm-attach-file" value="true" />
<!-- You need this if you want the voicemail attached -->
<param name="vm-message-ext" value="wav" />
<!-- Can be 'mp3' but needs mod_lame to be loaded. -->

Then, use fs_cli in /log 7 and leave a voicemail on a configured extension. After completing the voicemail, you should see something like this (both mailto and notify-mailto have been set in this case):

2012-02-02 18:21:36.494891 [DEBUG] mod_voicemail.c:2641 Deliver VM to 1001@
2012-02-02 18:21:36.894770 [DEBUG] switch_utils.c:761 Emailed file [/tmp/mail.1328206896cebf] to []
2012-02-02 18:21:36.894770 [DEBUG] mod_voicemail.c:2831 Sending message to
2012-02-02 18:21:37.394793 [DEBUG] switch_utils.c:763 Emailed data to []
2012-02-02 18:21:37.394793 [DEBUG] mod_voicemail.c:2881 Sending notify message to


Send Voice Mail to Email

The following is an example of sending a voicemail to email

<user id="1001" number-alias="1001">
<param name="password" value="1234" />
<param name="vm-password" value="4321" />
<param name="vm-email-all-messages" value="true" />
<param name="vm-attach-file" value="true" />
<param name="vm-mailto" value="" />
<variable name="accountcode" value="1001" />
<variable name="user_context" value="default" />

Send Call To Voice Mail

The following is an example of sending a call to voicemail after you've decided that a user isn't available.

<action application="answer"/>
<action application="voicemail" data="default $${domain} $1"/>

where '''default''' is the profile name (must be configured in voicemail.conf.xml), '''$${domain}''' is (obviously) the domain (in this case the system-wide domain setting for your switch from vars.xml) and '''$1''' is the dialed extension.

Check Voice Mail

The following is an example of checking vm (will prompt for PIN if ${voicemail_authorized} is not "true")

Please make sure the password is set in order for the mailbox to prompt for a password.

<action application="voicemail" data="check $${voicemail_profile} $${domain} $1"/>

The following example will allow the user to check vm whether they're "voicemail_authorized" or not. If voicemail_authorized=true , then user can access voicemail without prompting for password. If it's set to false, then the system will ask to enter the password. I found that even if you don't put <auth> in the following example, it will still check if it is authed. Someone please verify.

<action application="voicemail" data="check auth $${voicemail_profile} $${domain} $1"/>

To automatically pass all registered users on your domain without prompting to enter the password:

<action application="set" data="voicemail_authorized=${sip_authorized}"/>
<action application="voicemail" data="check auth $${voicemail_profile} $${domain} $1"/>

(Preliminary 2012.02.06) To speak the called party number before speaking the date of the voicemail message, enable channel variable vm_announce_cid. This only speaks the number, it does not preface it with introductory words such as "The caller's number is..." nor separate the number from the date that follows it.

<action application="set" data="vm_announce_cid=true" />
<action application="voicemail" data="check $${voicemail_profile} $${domain} $1"/>

Retrieve Voice Mail Via Web Interface


To enable the web interface for voice mail, you must first install/enable mod_xml_rpc

You also need to enable the user or domain to use the web interface using #http-allowed-api

There are two different URLs for retrieving voice mail via a browser.
The following are functionally equivalent:

* http://fs.ip:8080/api/voicemail/web
* http://fs.ip:8080/domains/this/api/voicemail/web

Enter the username and password in the challenge box. When authorized, the list of current voice mails will be displayed.<br/>
Note: use the actual IP address (or domain name) and not something like or "localhost" because it won't work.<br/>
Domains are used in various circumstances. Here are some scenarios:

In this case you could do this:

Log in with user and password and you are in

Alternatively, you could use the IP address:

Then login with and password

Finally, you could even do this:

And log in with just user and password (no

Retrieve Voice Mail Via IMAP Interface

This is not implemented yet.

See [[Bounty#IMAP integration of voicemail]]

Using voicemail to authenticate a caller's PIN

This example allows you to authenticate a user by requiring him/her to enter a PIN. If the user enters the correct PIN then dialplan processing continues. If not, then the system will play an error message and then disconnect the caller.

<action application="voicemail" data="check auth_only ${extension_number_against_which_to_check}"/>

you can also set the "vm_auth_only" channel variable to true before calling the voicemail application, instead of using the auth_only arg

Configuration Parameters


This is the extension which you want to use for the voicemail messages to be recorded. The default is wav but can be gsm, raw, ul, al, etc.

<param name="file-extension" value="wav"/>

Key FS Mapping

[[mod_voicemail key map]]


<param name="callback-dialplan" value="XML"/>


<param name="callback-context" value="default"/>


<param name="terminator-key" value="#"/>


<param name="max-login-attempts" value="3"/>


<param name="digit-timeout" value="10000"/>


<param name="max-record-len" value="300"/>


<param name="tone-spec" value="%(1000, 0, 640)"/>


<param name="play-new-messages-key" value="1"/>


<param name="play-saved-messages-key" value="2"/>
<param name="main-menu-key" value="0"/>


<param name="config-menu-key" value="5"/>


<param name="record-greeting-key" value="1"/>


<param name="choose-greeting-key" value="2"/>


<param name="record-name-key" value="3"/>


<param name="record-file-key" value="3"/>


<param name="listen-file-key" value="1"/>


<param name="save-file-key" value="2"/>


<param name="delete-file-key" value="7"/>


<param name="undelete-file-key" value="8"/>


<param name="email-key" value="4"/>


<param name="pause-key" value="0"/>


<param name="restart-key" value="1"/>


<param name="ff-key" value="6"/>


<param name="rew-key" value="4"/>


This option allows you to override the default sqlite with an ODBC handle. You can use any valid DSN from your odbc.ini to store your voicemail configuration

<param name="odbc-dsn" value="dsn:user:pass"/>


This parameter defines an 'energy level', it is a numeric value of how "quiet" the channel is.

See [[Misc. Dialplan Tools wait_for_silence#Description|DP Tool 'wait_for_silence']] for more info.

<param name="record-silence-threshold" value="200"/>


This parameter defines how many consecutive hits below record-silence-threshold it takes to end the recording.

See [[Misc. Dialplan Tools wait_for_silence#Description|DP Tool 'wait_for_silence']] for more info.

<param name="record-silence-hits" value="2"/>


Setting this value will set the from address on the email sent

<param name="email-from" value="${voicemail_account}@${voicemail_domain}"/>


If db-password-override=true, the db password will only be used if present, if not present fallback to the xml config file vm-password. By default, both values in voicemail db and xml config file work.

<param name="db-password-override" value="false"/>


If you want to have a non-standard location for the sqlite3 db, you can specify a different location for the profile.

<param name="dbname" value="/dev/shm/voicemail_default.db"/>


If allow-empty-password-auth=false, it will disable login via a authentication method if there is no password set in the user account (This wont affect voicemail_authorize=true login)

<param name="allow-empty-password-auth" value="true"/>


<param name="auto-playback-recordings" value="true"/>

Database Schema

This will be automatically created by FreeSWITCH if it does not already exist.

Voicemail Message Settings

-- #### Voicemail Message Settings #### --
CREATE TABLE voicemail_msgs (
created_epoch INTEGER, -- when this voicemail message was created
read_epoch INTEGER, -- when this voicemail message was read, '0' means its unread
username VARCHAR(255), -- recipient's username
domain VARCHAR(255), -- recipient's domain
uuid VARCHAR(255), -- call uuid which created this voicemail message
cid_name VARCHAR(255), -- sender caller-id name
cid_number VARCHAR(255), -- sender caller-id number
in_folder VARCHAR(255), -- voicemail box folder name
file_path VARCHAR(255), -- physical path to voicemail message on disk
message_len INTEGER, -- length of voiemail message in seconds
flags VARCHAR(255), -- voicemail message status, 'save' (saved message) | 'delete' (deleted message) | ' ' (normal message)
read_flags VARCHAR(255), -- voicemail message priority, 'A_URGENT' | 'B_NORMAL'
forwarded_by VARCHAR(255) -- n/a

Voicemail User Preferences

-- #### Voicemail User Preferences #### --
CREATE TABLE voicemail_prefs (
username VARCHAR(255), -- voicemail user's name
domain VARCHAR(255), -- voicemail user's domain
name_path VARCHAR(255), -- named path of user defined greeting file (see [[#vm_prefs]])
greeting_path VARCHAR(255), -- physical path to user defined greeting file (see [[#vm_prefs]])
password VARCHAR(255) -- voicemail user's password
create index voicemail_msgs_idx1 on voicemail_msgs(created_epoch);
create index voicemail_msgs_idx2 on voicemail_msgs(username);
create index voicemail_msgs_idx3 on voicemail_msgs(domain);
create index voicemail_msgs_idx4 on voicemail_msgs(uuid);
create index voicemail_msgs_idx5 on voicemail_msgs(in_folder);
create index voicemail_msgs_idx6 on voicemail_msgs(read_flags);
create index voicemail_msgs_idx7 on voicemail_msgs(forwarded_by);
create index voicemail_msgs_idx8 on voicemail_msgs(read_epoch);
create index voicemail_msgs_idx9 on voicemail_msgs(flags);
create index voicemail_prefs_idx1 on voicemail_prefs(username);
create index voicemail_prefs_idx2 on voicemail_prefs(domain);



vm_boxcount can be called from console, xml_rpc or any other interface that exposes FreeSWITCH API.

The function takes the following arguments:


and defaults to "new" voicemails and to the "default" voicemail profile.


vm_boxcount myprofile/|new
vm_boxcount 0001@default|saved (defaults to "default" voicemail profile)


<user>@<domain>[@<profile>] <sound_file> [<cid_num>] [<cid_name>]

voicemail_inject is used to add an arbitrary sound file to a users voicemail mailbox.


vm_prefs [profile/]<user>@<domain>[|[name_path|greeting_path|password]]
vm_prefs is used to check the preference changed by user
vm_prefs 1000@|name_path|greeting_path|password


vm_prefs 1000@|greeting_path



vm_list <id>@<domain>[/profile] [xml]
vm_list is used to get list of all the voicemails for the user

vm_list 1000@

1303500797:1303501043:1000: 1001:1001

vm_list 1001@ xml


vm_delete <id>@<domain>[/profile] [<uuid>]


vm_read <id>@<domain>[/profile] <read|unread> [<uuid>]

Advanced API

This advanced API was introduced in Apr 2011. It provides for configuring voicemail as well as the retrieval of voicemail related information. Using this api avoids needing to access voicemail_defaults.db directly. It was created for use with [[Mod_voicemail_ivr]], and was as well used in some GUI implementations.

This is also the base reference API for future [[Mod_voicemail_ivr]] improvement.


vm_fsdb_pref_password_set <profile> <domain> <userid> <new-password>
Sets the mailbox password


vm_fsdb_pref_greeting_set <profile> <domain> <userid> <slot> [file-path]
Sets the file in file_path as the current greeting in voicemail_prefs table (voicemail_defaults.db)

<need to determine the slot parameter action>

The voicemail_prefs table is updated to reflect the currently active greeting

Returns -ERR if the file is not present


vm_fsdb_pref_recname_set <profile> <domain> <user> <file-path>
Sets or updates (if there is already a name file path) the file in file-path as the current name recording in voicemail_prefs

returns -ERR if the file is not present


vm_fsdb_msg_list <format> <profile> <domain> <user> <folder> <filter>
<format> is ignored but must be present
<folder> For future implementation but must be present
<filter> If none specified, then all messages are returned. Support the following filter :
* not-read
* new
* save
freeswitch@default> vm_fsdb_msg_list 0 default 1000 0 new ASC

Returns the list of unread messages for the user@domain for Inbox in JSON format

This function returns only New messages so it is not a full replacement for vm_list


vm_fsdb_msg_list <profile> <domain> <user> <uuid> <email address>
freeswitch@default> vm_fsdb_msg_email default 1000 1dfdc31c-7615-4e54-bfbc-dadacc3e5807


vm_fsdb_msg_purge <profile> <domain> <user>
This function purges voicemails marked as Delete for the user@domain

Returns -OK or -ERR (if missing a parameter or profile not found)


vm_fsdb_msg_delete <profile> <domain> <user> <uuid>
Deletes the message specified by uuid for user@domain

returns -OK or -ERR (if missing parameter or profile not found)


vm_fsdb_msg_save <profile> <domain> <user> <uuid>
Marks the file specified by uuid for user@domain to 'save'

Returns -OK or -ERR if missing a parameter or profile not found


vm_fsdb_msg_undelete <profile> <domain> <user> <uuid>
Clears the flags field (regardless of whether it was 'delete' or not)

Returns -OK or -ERR if missing a paramter or profile is not found


vm_fsdb_auth_login <profile> <domain> <user> <password>
password is assumed to be 64 chars or less

Seems to verify that the password in voicemail_prefs is same as in xml?????

Returns -OK or -ERR if:
#missing parameters or profile not found
#password in voicemail_prefs doesn't match password passed in call
#password in xml does not match password passed in call
#"Login Denied" if vm is disabled
If a password exists in voicemail_prefs, it is used in preference to xml


vm_fsdb_msg_get <format> <profile> <domain> <user> <uuid>
<format> is ignored but must be present

Returns a JSON formatted list detailing the VM
or -ERR if missing parameters or profile is not found

Assumes that the uuid can exist in more than 1 row of voicemail_msgs


vm_fsdb_msg_count <format> <profile> <domain> <user> <folder>
Returns a count of the number of read and unread VM's in the Inbox folder for this user@domain

Counts are returned in JSON format for
(VM's in other folders are not counted but includes VM's marked as delete or save)

Returns -ERR if missing a parameter or if profile is not found


How do I reload new configuration without restarting FreeSWITCH?

If you happened to change settings in autoload_configs/voicemail.conf.xml and would like to make it effective without restarting FreeSWITCH, enter the following command in console mode in sequence:

reload mod_voicemail

Do I need a text-to-speech engine installed?

No, it will work with sound files or a text-to-speech engine.

How do I install sound files?

make sounds-install

Voicemail Voice Prompt / Troubleshooting Problems

Unfortunately mod_voicemail does not have a great ability to be debugged, even with logging turned up tracking down errors can be tricky and an incorrect config upgrade can leave you without working voicemail. Make sure that dialed_extension is SET and exported (you can use the info app to verify) as if this variable is not set voicemail will most likely not be working for you.

If you encounter a problem where the voice mail prompts are either missing, or fail to play with this error on the console:

switch_ivr_phrase_macro() Macro [voicemail_config_menu] did not match any patterns


Can't find macro

This is caused by a missing voicemail prompt sound file or invalid conf/lang files.
You will need to perform the corrective command below in the FreeSWITCH source directory:

make vm-sync

After you run the make vm-sync, you'll need to do a reloadxml at the FreeSWITCH console, or restart FreeSWITCH. If the error is in certain xml files then this may not fix it, try to temporarily replace your conf/lang folder with that from trunk (or the base install).

If you've installed french sound files, you have to do the following:
* rename `conf/lang/fr/ca/vm/sounds.xml` to `conf/lang/fr/ca/vm/tts.xml`
* copy `conf/lang/en/us/vm/sounds.xml` to `conf/lang/fr/ca/vm/sounds.xml`

How to update keys for accessing voicemail from outside?

You need to edit the /<path to freeswitch>/conf/autoload_configs/voicemail.conf.xml file.

<param name="login-keys" value="0"/>
-Key to prompt the voicemail's password
<param name="vmain-key" value="*"/>
-Key to prompt the voicemail's UserID
The login-keys param is the key to prompt the password, while the vmain-key is the key to prompt the UserID.

How can I disable remote login/access to voicemail?

Set the following two params in autoload_configs/voicemail.conf.xml:

<param name="vmain-key" value="a"/>
<param name="login-keys" value="a"/>

Can I share voicemail boxes between multiple phones/users?

To Monitor Voicemail

There are 2 ways to do this, the correct way would be to use the subscribe feature of your phone to monitor a particular mailbox

1. SUBSCRIBE feature method

: The phones in question all need to support using SUBSCRIBE to monitor their mailbox.<br/>
: Phones that use other methods (ie. gratuitous/parasitic "NOTIFY" style) will not work.<br/>
: Other concerns you may face include: whether you can configure the extension dialed when you press the 'retrieve' button.<br/>
: This configuration tested successfully on two SNOM 320 handsets, but fails on the Cisco 7960 because it does not use SUBSCRIBE.<br/>

SNOM 320 configuration

This configuration tested with firmware 7.1.30 and newer.<br/>
* Under 'Identity-->Login', set Mailbox to the shared box number.

2. Force MWI Info in Sofia

: To populate the param MWI-Account of the directory user (or domain) with user@domain of the voicemail you want to monitor.
: This will force sofia to send the MWI info for that mailbox even if you registred for another phone. This method only allow you to monitor mailbox

<param name="MWI-Account" value="1000@$${domain}"/>

To Receive Voicemail

''receiving voicemail into the shared mailbox (e.g. when no answer)''

In each user's directory entry, add a variable named 'mailbox' that looks like this:

<variable name="mailbox" value="1500"/>

This sets the stage for which mailbox they're actually going to use, shared or not.. it is used ONLY in the dialplan.
Change your dialplan to reflect this:

The old entry:

<action application="voicemail" data="default ${domain_name} ${dialed_extension}"/>

The new entry:

<action application="voicemail" data="default ${domain_name} ${user_data(${dialed_extension}@${domain_name} var mailbox)}"/>

Voicemail Callback

''calling back a caller while checking voicemail''

When a user is listening to voicemail messages - they are able to dial '5' and be connected to the caller of that voicemail.

You are able to control the dial plan execution of this callback method by modifying the vm_callback.xml file located under BASE_FREESWITCH_DIR/conf/dialplan

An example vm_callback.xml is as follows:

<context name="vm_callback">
<extension name="vm_return_call">
<condition field="destination_number" expression="^(\+1|\+)?(\d+)$">
<action application="info" />
<action application="bridge" data="sofia/vm/+1$2@GATEWAY" />
/usr/bin/python /home/chronos_client/persistent/ -l -i -d -f -t

Transcribing Voicemail

There's no real simple way to do this as of now with mod_voicemail.

If you use Fusionpbx's mailer for FS, then you can intercept the wav file mid-mailing and send it to some sort of API.

NOTE: "Transcription" is the full text, where as IVR speech recognition is to recognize audio vs a specific list of options, "grammar". These are very different things.

The available APIs for some sort of transcription are:

  • twilio - 5cents/minute
  • voicecloud - 10cents/minute. They seem to have a $250/month minumum.
  • tropo - 3 cents/minute I think (60 second billing) BUT they need to record the file, on their system. They have all-SIP plans with alternate billing.
  • quicktate - $0.0175/word, volume at 1.10cents/word. Avg of 160 words per minute = $2.80/minute.
  • mycaption - 9c/minute for purely machine-based.
  • mycaption - 43c/minute upto 55c/minute - 15 second increments -premium that combines machine-based speech recognition with error correction by human editors.
  • Google speech API - free, but it's not that great as of right now. Some info on how to access it here.

Here is a script you can use for tinkering with Google Speech API:

Google Speech API

echo "1 SoX Sound Exchange - Convert WAV to FLAC with 16000"
sox $1 message.flac pad .1 0 rate 16k
echo "2 Submit to Google Voice Recognition"
wget -q -U "Mozilla/5.0" --post-file message.flac --header="Content-Type: audio/x-flac; rate=16000" -O - "" > message.ret
echo "3 SED Extract recognized text"
cat message.ret | sed 's/.*utterance":"//' | sed 's/","confidence.*//' > message.txt
echo "4 Remove Temporary Files"
rm message.flac
# rm message.ret
echo "5 Show Text "
cat message.txt


./ /usr/local/freeswitch/sounds/en/us/callie/ivr/8000/ivr-one_more_mistake.wav 1 SoX Sound Exchange - Convert WAV to FLAC with 16000 2 Submit to Google Voice Recognition 3 SED Extract recognized text 4 Remove Temporary Files 5 Show Text that's odd 1 more mistake and I will hang up on your ass

It should be "that's it" instead of "that's odd" but otherwise Google actually got it right. Try other sound prompts.


there are few useful variables for skipping post messages: skip_record_urgent_check and skip_record_check Posted by alexey_khabulyak at Jul 18, 2018 09:00