mod_voicemail
About
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
- 1 Synopsis
- 2 Dialplan variables
- 3 Controlling User Parameters & Variables
- 3.1 vm-enabled
- 3.2 vm-alternate-greet-id
- 3.3 voicemail_alternate_greet_id
- 3.4 voicemail_greeting_number
- 3.5 http-allowed-api
- 3.6 vm-disk-quota
- 3.7 vm-mailto
- 3.8 vm-mailfrom
- 3.9 vm-notify-mailto
- 3.10 vm-password
- 3.11 vm-a1-hash
- 3.12 vm-email-all-messages
- 3.13 vm-notify-email-all-messages
- 3.14 vm_cc
- 3.15 vm-keep-local-after-email
- 3.16 vm-attach-file
- 3.17 vm-message-ext
- 3.18 vm_message_ext
- 3.19 vm-skip-instructions
- 3.20 notify-template-file
- 3.21 vm-storage-dir
- 3.22 vm-storage-dir-shared
- 3.23 vm-domain-storage-dir
- 4 Using Outside Programs to Send Voicemail to Email
- 5 Send_mail setting
- 6 Exim4 settings
- 7 Windows settings
- 8 Mail via PHP
- 9 nullmailer settings
- 10 sSMTP settings
- 11 Debugging an external mailer
- 12 Example
- 13 Configuration Parameters
- 13.1 file-extension
- 13.2 Key FS Mapping
- 13.3 callback-dialplan
- 13.4 callback-context
- 13.5 terminator-key
- 13.6 max-login-attempts
- 13.7 digit-timeout
- 13.8 max-record-len
- 13.9 tone-spec
- 13.10 play-new-messages-key
- 13.11 play-saved-messages-key
- 13.12 main-menu-key
- 13.13 config-menu-key
- 13.14 record-greeting-key
- 13.15 choose-greeting-key
- 13.16 record-name-key
- 13.17 record-file-key
- 13.18 listen-file-key
- 13.19 save-file-key
- 13.20 delete-file-key
- 13.21 undelete-file-key
- 13.22 email-key
- 13.23 pause-key
- 13.24 restart-key
- 13.25 ff-key
- 13.26 rew-key
- 13.27 odbc-dsn
- 13.28 record-silence-threshold
- 13.29 record-silence-hits
- 13.30 email-from
- 13.31 db-password-override
- 13.32 dbname
- 13.33 allow-empty-password-auth
- 13.34 auto-playback-recordings
- 14 Database Schema
- 15 API
- 15.1 vm_boxcount
- 15.2 voicemail_inject
- 15.3 vm_prefs
- 15.4 vm_list
- 15.5 vm_delete
- 15.6 vm_read
- 16 Advanced API
- 16.1 vm_fsdb_pref_password_set
- 16.2 vm_fsdb_pref_greeting_set
- 16.3 vm_fsdb_pref_recname_set
- 16.4 vm_fsdb_msg_list
- 16.5 vm_fsdb_msg_email
- 16.6 vm_fsdb_msg_purge
- 16.7 vm_fsdb_msg_delete
- 16.8 vm_fsdb_msg_save
- 16.9 vm_fsdb_msg_undelete
- 16.10 vm_fsdb_auth_login
- 16.11 vm_fsdb_msg_get
- 16.12 vm_fsdb_msg_count
- 17 FAQ
- 18 How do I reload new configuration without restarting FreeSWITCH?
- 19 Do I need a text-to-speech engine installed?
- 20 How do I install sound files?
- 21 Voicemail Voice Prompt / Troubleshooting Problems
- 22 How to update keys for accessing voicemail from outside?
- 23 How can I disable remote login/access to voicemail?
- 24 Can I share voicemail boxes between multiple phones/users?
- 24.1 To Monitor Voicemail
- 24.1.1 1. SUBSCRIBE feature method
- 24.1.2 SNOM 320 configuration
- 24.1.3 2. Force MWI Info in Sofia
- 24.1.1 1. SUBSCRIBE feature method
- 24.2 To Receive Voicemail
- 24.3 Voicemail Callback
- 24.1 To Monitor Voicemail
- 25 Transcribing Voicemail
Synopsis
voicemail,Voicemail,[check] [auth] <profile_name> <domain_name> [<id>]
Dialplan variables
skip_greeting
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"/>
skip_instructions
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_instructions=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}"/>
voicemail_callback_dialplan
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"/>
voicemail_callback_context
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="voicemail_callback_context=mydomain.com"/>
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
vm-enabled
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.
vm-alternate-greet-id
voicemail_alternate_greet_id
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 -->
<include>
<user id="1004">
<params>
<param name="password" value="xyzzy"/>
<param name="vm-password" value="1234"/>
<param name="vm-alternate-greet-id" value="8661234567"/>
</params>
<variables>
<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"/>
</variables>
</user>
</include>
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}"/>
</condition>
</extension>
voicemail_greeting_number
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.
http-allowed-api
This allows the user to use the web vm
<param name="http-allowed-api" value="voicemail"/>
vm-disk-quota
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"/>
vm-mailto
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="user101@mydomain.com" />
vm-mailfrom
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="noreply@yourdomain.com" />
in the voicemail template you can get this value using: ${voicemail_email_from}
vm-notify-mailto
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="user101_manager@yourdomain.com" />
vm-password
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.
Example:
<param name="vm-password" value="12345" />
vm-a1-hash
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 "101:mydomain.com:12345" -->
<param name="vm-a1-hash" value="fd5184d9d36a2009c72e1571abf0493e" />
vm-email-all-messages
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" />
vm-notify-email-all-messages
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" />
vm_cc
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="vm_cc=1001@mydomain.com"/>
<action application="voicemail" data="default mydomain.com 1000"/>
<!--If you want to cc the message to multiple users, use a comma separated list of users:-->
<action application="set" data="vm_cc=1001@mydomain.com,1002@mydomain.com,1003@mydomain.com"/>
Directory Example:
<include>
<domain name="mydomain.com">
<user id="101">
<params>
<!--Note: for user directory you can use either vm_cc in variables or the vm-cc param-->
<param name="vm-cc" value="1001@mydomain.com,1002@mydomain.com,1003@mydomain.com" />
</params>
<varibles>
<variable name="vm_cc" value="1001@mydomain.com" />
<!--If you want to cc the message to multiple users, use a comma separated list of users:-->
<variable name="vm_cc" value="1001@mydomain.com,1002@mydomain.com,1003@mydomain.com" />
</varibles>
</user>
</domain>
</include>
vm-keep-local-after-email
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
Example:
<param name="vm-keep-local-after-email" value="false" />
vm-attach-file
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.
Example:
<param name="vm-attach-file" value="true" />
vm-message-ext
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'.
Example:
<param name="vm-message-ext" value="mp3"/>
vm_message_ext
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.
Example:
<variable name="vm_message_ext" value="mp3"/>
vm-skip-instructions
This disables instructions for how to leave a message, and instead just plays a beep.
<param name="vm-skip-instructions" value="true"/>
notify-template-file
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"/>
vm-storage-dir
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).
Example:
<param name="vm-storage-dir" value="/home/voicemail/test.com/100"/>
Note: Most users either save voicemails locally, on a network file share directory or using a distribusted network file system, like glusterFS. https://www.gluster.org 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.
http://lists.freeswitch.org/pipermail/freeswitch-users/2016-August/121650.html
vm-storage-dir-shared
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:
<storage_dir>/<realm>/voicemail/<id>
Example:
<param name="vm-storage-dir-shared" value="true"/>
vm-domain-storage-dir
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/example.com, it will store VM in /var/lib/freeswitch/storage/test.com/user_id.
Example:
<param name="vm-domain-storage-dir" value="/var/lib/voicemail/test.com/"/>
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
#!/usr/bin/python
#
"""
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.
THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
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
SERVER = 'smtp.gmail.com'
PORT = 587
USER = 'YOUR_MAIL_USER'
PASSWORD = 'PASSWORD'
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')
else:
#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')
fh.write(data)
fh.close()
# send the mail
def send(sender,to,message,verbose=False):
smtp = smtplib.SMTP(SERVER, PORT)
if verbose:
smtp.set_debuglevel(1)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login(USER,PASSWORD)
smtp.sendmail(sender, to, message)
smtp.quit()
def mail(sender='', to='', subject='', text='', attachments=None, verbose=False):
"""
Usage:
mail()
Params:
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')
writer.startmultipartbody('mixed')
# start with a text/plain part
part = writer.nextpart()
body = part.startbody('text/plain')
part.flushheaders()
body.write(text)
# 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'
else:
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
writer.lastpart()
send(sender,to,message.getvalue(),verbose)
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(email_addr.search(fromAddress))
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."
exit(1)
if options.toAddress:
to = options.toAddress
if not validate_email(to):
print "Invalid To email address. Please try again."
exit(1)
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})(\]?))>')
if to_field.search(message):
to_match = to_field.search(message)
to = str(to_match.group(1))
if log:
write_file('/tmp/sendemail.log',message)
send(fromAddress,to,message,verbose)
else:
if translate == 'tiff2pdf':
tempfile = "/tmp/%s.pdf" % os.path.basename(infile)
command = "tiff2pdf %s -o %s" % (infile, tempfile)
os.system(command)
attachment = tempfile
else:
attachment = infile
attach=[attachment]
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:
os.unlink(tempfile)
if delete and attachment:
os.unlink(attachment)
Make the following changes to /usr/local/freeswitch/autoload_configs/switch.conf.xml:
<param name="mailer-app" value="/usr/local/freeswitch/scripts/sendemail.py"/>
<param name="mailer-app-args" value="-i -d -f freeswitch@mydomain.com -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 [http://lists.freeswitch.org/pipermail/freeswitch-users/2009-June/043660.html here],[http://lists.freeswitch.org/pipermail/freeswitch-users/2010-January/052529.html here] and [http://jira.freeswitch.org/browse/FS-1923 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 [http://jira.freeswitch.org/browse/FS-5332 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 someone@someaddress.net
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 "someone@someaddress.net" is the actual recipient of the email message, but exim's default behavior takes the argument from the command line and subtracts the "someone@someaddress.net" 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:
eximcompat.sh:
#!/bin/bash
exec exim4 -t
And then pointing the mailer app to this script:
<param name="mailer-app" value="/usr/local/bin/eximcompat.sh"/>
<!-- <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 exim4compat.sh 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
host 127.0.0.1
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
http://untroubled.org/nullmailer/ 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
http://wiki.debian.org/sSMTP can be used as a null mailer and has the advantage over http://untroubled.org/nullmailer/ 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 freeswitch@mydomain.com"/>
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
mailhub=smtp.mydomain.com:587
UseTLS=YES
UseSTARTTLS=YES
AuthUser=myusername
AuthPass=mypassword
rewriteDomain=mydomain.com # This is useful if your FS box is not in DNS or has a different domain from the sending email
hostname=myFShostname.domain
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: <freeswitch@mydomain.com>
To: <testuser@mydomain.com>
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 freeswitch@mydomain.com testuser@mydomain.com
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 freeswitch@mydomain.com"/>
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="user.name@mydomain.com" />
<!-- or just notify -->
<param name="vm-notify-mailto" value="user.name@mydomain.com" />
<!-- 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@192.168.100.100
2012-02-02 18:21:36.894770 [DEBUG] switch_utils.c:761 Emailed file [/tmp/mail.1328206896cebf] to [user.name@mydomain.com]
2012-02-02 18:21:36.894770 [DEBUG] mod_voicemail.c:2831 Sending message to user.name@mydomain.com
2012-02-02 18:21:37.394793 [DEBUG] switch_utils.c:763 Emailed data to [user.name@mydomain.com]
2012-02-02 18:21:37.394793 [DEBUG] mod_voicemail.c:2881 Sending notify message to user.name@mydomain.com
Example
Send Voice Mail to Email
The following is an example of sending a voicemail to email
<include>
<user id="1001" number-alias="1001">
<params>
<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="example@yahoo.com" />
</params>
<variables>
<variable name="accountcode" value="1001" />
<variable name="user_context" value="default" />
</variables>
</user>
</include>
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
Configuration
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 127.0.0.1 or "localhost" because it won't work.<br/>
Domains are used in various circumstances. Here are some scenarios:
- your.domain.com is on the public Internet
In this case you could do this:
http://your.domain.com:8080/api/voicemail/web
Log in with user and password and you are in
Alternatively, you could use the IP address:
http://1.2.3.4:8080/api/voicemail/web
Then login with user@your.domain.com and password
Finally, you could even do this:
http://1.2.3.4:8080/domains/your.domain.com/api/voicemail/web
And log in with just user and password (no @your.domain.com)
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
file-extension
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]]
callback-dialplan
<param name="callback-dialplan" value="XML"/>
callback-context
<param name="callback-context" value="default"/>
terminator-key
<param name="terminator-key" value="#"/>
max-login-attempts
<param name="max-login-attempts" value="3"/>
digit-timeout
<param name="digit-timeout" value="10000"/>
max-record-len
<param name="max-record-len" value="300"/>
tone-spec
<param name="tone-spec" value="%(1000, 0, 640)"/>
play-new-messages-key
<param name="play-new-messages-key" value="1"/>
play-saved-messages-key
<param name="play-saved-messages-key" value="2"/>
main-menu-key
<param name="main-menu-key" value="0"/>
config-menu-key
<param name="config-menu-key" value="5"/>
record-greeting-key
<param name="record-greeting-key" value="1"/>
choose-greeting-key
<param name="choose-greeting-key" value="2"/>
record-name-key
<param name="record-name-key" value="3"/>
record-file-key
<param name="record-file-key" value="3"/>
listen-file-key
<param name="listen-file-key" value="1"/>
save-file-key
<param name="save-file-key" value="2"/>
delete-file-key
<param name="delete-file-key" value="7"/>
undelete-file-key
<param name="undelete-file-key" value="8"/>
email-key
<param name="email-key" value="4"/>
pause-key
<param name="pause-key" value="0"/>
restart-key
<param name="restart-key" value="1"/>
ff-key
<param name="ff-key" value="6"/>
rew-key
<param name="rew-key" value="4"/>
odbc-dsn
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"/>