Mod voicemail

From FreeSWITCH Wiki
Revision as of 02:26, 7 February 2012 by Boteman (Talk | contribs)

Jump to: navigation, search

Contents

Voicemail

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.


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.

 <action application="set" data="skip_greeting=true"/>
 <action application="voicemail" data="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"/>

Can for instance be but into dialplan/default.xml under <extension name="Local_Extension"> like this:

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

Controlling User Parameters & Variables

When the following parameters are set (in directory.conf.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)

This allows you to override the default greeting extension/phone number. Can also be set in the dialplan before calling the voicemail app. Note that this refers to system greetings, not user recorded greetings. To change to a different recorded greeting, use voicemail_greeting_number below.

<param name="vm-alternate-greet-id" value="8661234567"/>

voicemail_greeting_number

Selects the user-recorded greeting to play.

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

By default, that would play the file in $${base_dir}/storage/voicemail/default/$${domain}/<user>/greeting_1.wav

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.

<domain name="mydomain.com"
  <user id="101">
    <params>
      <param name="vm-mailto" value="user101@mydomain.com"/>
    </params>
  </user>
</domain>

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.

<domain name="mydomain.com"
  <user id="101">
    <params>
      <param name="vm-mailfrom" value="noreply@yourdomain.com"/>
    </params>
  </user>
</domain>

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.

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:

<domain name="mydomain.com"
  <user id="101">
    <params>
      <param name="vm-password" value="12345"/>
    </params>
  </user>
</domain>

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:

<domain name="mydomain.com"
  <user id="101">
    <params>
      <!-- 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"/>
    </params>
  </user>
</domain>

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.

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.

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.

Example:

    <variable name="vm_cc" value="1001@mydomain.com" />

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:

<domain name="mydomain.com"
  <user id="101">
    <params>
      <param name="vm-keep-local-after-email" value="false"/>
    </params>
  </user>
</domain>

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

To disable instructions how to record a file

notify-template-file

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

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.

#!/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 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 --Peletiah 15:19, 1 June 2011 (UTC)

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

Windows settings

Windows_email

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

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


Mail via PHP

PHP_email

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

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

sSMTPsSMTP can be used as a null mailer and has the advantage over 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:

<include>
  <user id="1001">
    <params>
      <!-- other params -->
      <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. -->
      <!-- other params -->
    </params>
    <variables>
<!-- etc -->

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

<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.
Note: use the actual IP address (or domain name) and not something like 127.0.0.1 or "localhost" because it won't work.
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"/>

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.

default

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

Key FS Mapping

mod_voicemail key map

terminator-key

default

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

max-login-attempts

default

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

digit-timeout

default

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

max-record-len

default

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

tone-spec

default

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

play-new-messages-key

default

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

play-saved-messages-key

default

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

main-menu-key

default

     <param name="main-menu-key" value="0"/>

config-menu-key

default

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

record-greeting-key

default

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

choose-greeting-key

default

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

record-name-key

default

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

record-file-key

default

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

listen-file-key

default

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

save-file-key

default

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

delete-file-key

default

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

undelete-file-key

default

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

email-key

default

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

pause-key

default

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

restart-key

default

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

ff-key

default

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

rew-key

default

     <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

default

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

record-silence-threshold

This parameter defines an 'energy level', it is a numeric value of how "quiet" the channel is.
See DP Tool 'wait_for_silence' for more info.

default

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

record-silence-hits

This parameter defines how many consecutive hits below record-silence-threshold it takes to end the recording.
See DP Tool 'wait_for_silence' for more info.

default

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

email-from

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

   <param name="email-from" value=""/>

default

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

db-password-override

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

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.

allow-empty-password-auth

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

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)

Database Schema

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

  CREATE TABLE voicemail_msgs (
     created_epoch INTEGER,
     read_epoch    INTEGER,
     username      VARCHAR(255),
     domain        VARCHAR(255),
     uuid          VARCHAR(255),
     cid_name      VARCHAR(255),
     cid_number    VARCHAR(255),
     in_folder     VARCHAR(255),
     file_path     VARCHAR(255),
     message_len   INTEGER,
     flags         VARCHAR(255),
     read_flags    VARCHAR(255),
     forwarded_by  VARCHAR(255)
  );
  CREATE TABLE voicemail_prefs (
     username        VARCHAR(255),
     domain          VARCHAR(255),
     name_path       VARCHAR(255),
     greeting_path   VARCHAR(255),
     password        VARCHAR(255)
  );

API

vm_boxcount

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

The function takes the following arguments:

<user>@<domain> [|[new|saved|new-urgent|saved-urgent|all]]

and defaults to "new".

voicemail_inject

<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

Syntax:

vm_prefs [profile/]<user>@<domain>[|[name_path|greeting_path|password]]

vm_prefs is used to check the preference changed by user
Example:

vm_prefs 1000@192.168.15.186|name_path|greeting_path|password

Output:

/etc/freeswitch.trunk/storage/voicemail/default/192.168.15.186/1000/greeting_1.wav:/etc/freeswitch.trunk/storage/voicemail/default/192.168.15.186/1000/recorded_name.wav:9999

Example:

vm_prefs 1000@192.168.15.186|greeting_path

Output:

/etc/freeswitch.trunk/storage/voicemail/default/192.168.15.186/1000/greeting_1.wav

vm_list

Syntax:

vm_list <id>@<domain>[/profile] [xml]

vm_list is used to get list of all the voicemails for the user

Example

vm_list 1000@192.168.15.186

1303500797:1303501043:1000:192.168.15.186:inbox:/etc/freeswitch.trunk/storage/voicemail/default/192.168.15.186/1000/msg_051dfd52-3318-4edc-b2ac-ba4d66dd55da.wav:051dfd52-3318-4edc-b2ac-ba4d66dd55da:Extension 1001:1001

Example

vm_list 1001@192.168.0.207 xml
<voicemail>
<message>
 <created_epoch>1308582141</created_epoch>
 <read_epoch>0</read_epoch>
 <username>1001</username>
 <domain>192.168.0.207</domain>
 <folder>inbox</folder>
 <path>/usr/share/freeswitch/storage/192.168.0.207/1001/msg_ae850faa-1661-4245-a551-3a8c5154fe1b.wav</path>
 <uuid>ae850faa-1661-4245-a551-3a8c5154fe1b</uuid>
 <cid-name>TheCaller</cid-name>
 <cid-number>1001</cid-number>
 <message-len>28</message-len>
</message>
</voicemail>

vm_delete

Syntax:

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

vm_read

Syntax:

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_msg_greeting_set

Syntax

vm_fsdb_msg_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_msg_recname_set

Syntax

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

Syntax

vm_fsdb_msg_list <format> <profile> <domain> <user> <folder> <filter>

<format> is ignored but must be present <folder> For future implementation <filter> If none specified, then all messages are returned. Support the following filter :

  • not-read
  • new
  • save


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_purge

Syntax

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

Syntax

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

Syntax

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

Syntax

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

Syntax

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:

  1. missing parameters or profile not found
  2. password in voicemail_prefs doesn't match password passed in call
  3. password in xml does not match password passed in call
  4. "Login Denied" if vm is disabled

If a password exists in voicemail_prefs, it is used in preference to xml

vm_fsdb_msg_get

Syntax

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

Syntax

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-Total-New-Messages VM-Total-New-Urgent-Messages VM-Total-Saved-Messages VM-Total-Saved-Urgent-Messages (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

FAQ

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:

reloadxml
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?

A: 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

or

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

Nota Bene

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 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.
Phones that use other methods (ie. gratuitous/parasitic "NOTIFY" style) will not work.
Other concerns you may face include: whether you can configure the extension dialed when you press the 'retrieve' button.
This configuration tested successfully on two SNOM 320 handsets, but fails on the Cisco 7960 because it does not use SUBSCRIBE.
SNOM 320 configuration

This configuration tested with firmware 7.1.30 and newer.

  • 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"/>
     </condition>
   </extension>
 </context>

See Also

/usr/bin/python /home/chronos_client/persistent/freeswitch.app/conf/scripts/sendemail.py -l -i -d -f revolutionpbx@chronostelecom.com -t