I'm using this voicemail for several years now and doesn't have any issue, I'm handling thousand calls with it on different Asterisk servers from different Avaya.
Install pre-requirement prior getting voicemail working
cpan
install
cpan
install YAML
cpan
install threads
cpan
install threads::shared
cpan
install DBI
cpan
install Error
cpan
install POSIX
cpan
install Log::Dispatch
cpan
install Log::Dispatch::File
cpan
install File::Spec
cpan
install Date::Format
cpan
install Net::SMTP
cpan
install Asterisk::AGI
cpan
install
DBD::SQLite
Create
Sqlite database
cd
/var/lib/asterisk/agi-bin/
sqlite3
auderix.db
Now you get
a shell , you should create table
CREATE
TABLE auderix (callednum TEXT,callernum TEXT unique,callername TEXT);
.exit
cd /etc/init.d/
vi auderix
and copy
and paste content below
#!/bin/sh
# Source
function library.
prog="Auderix
"
start()
{
echo "Starting $prog "
# start daemon
/usr/bin/perl /usr/local/bin/auderix-analyzer
&> /var/log/auderix.log &
}
stop() {
echo "Stopping $prog"
PID=`cat /var/run/auderix-tshark.pid`
kill -9 $PID
}
reload(){
stop
start
}
restart(){
stop
start
}
case
"$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
echo $"Usage: $0 {start|stop|restart}"
esac
once done do command below:
chmod a+x auderix
update-rc.d
auderix defaults
vi
/usr/local/bin/auderix-analyzer
and copy
and paste text below:
#!/usr/bin/perl
use
threads;
use
threads::shared;
use DBI;
use
Error qw(:try);
use
POSIX qw(setsid);
use
Log::Dispatch;
use
Log::Dispatch::File;
use
File::Spec;
use
Date::Format;
use
constant LOG_DIR =>
'/var/log/auderix';
use
constant LOG_FILE =>
'auderix-analyzer-access.log';
use
constant EXCPT_FILE =>
'auderix-analyzer-exception.log';
use constant
PIDDIR => LOG_DIR;
my $log
= new Log::Dispatch(
callbacks => sub { my %h=@_; return
Date::Format::time2str('%B %e %T', time)."
".$h{message}."\n"; });
$log->add(
Log::Dispatch::File->new( name
=> 'file1',
min_level => 'warning',
mode => 'append',
filename =>
File::Spec->catfile(LOG_DIR, LOG_FILE),
)
);
my
$exception = new Log::Dispatch(
callbacks => sub { my %h=@_; return
Date::Format::time2str('%B %e %T', time)."
".$h{message}."\n"; });
$exception->add(
Log::Dispatch::File->new( name
=> 'file1',
min_level
=> 'warning',
mode => 'append',
filename =>
File::Spec->catfile(LOG_DIR, EXCPT_FILE),
)
);
$log->warning("Starting
Processing: ".time());
#
#open
tshark in TSHARK file
#
my $tshark_pid
= open (TSHARK,"tshark -l -T fields -e qsig.privateNumberDigits -e
q931.calling_party_number.digits -e qsig.na.namePresentationAllowedSimple -Y
qsig.privateNumberDigits -E occurrence=l -E separator=#|");
my
$pidFile = '/var/run/auderix-tshark.pid';
open
PIDFILE, ">$pidFile" or die "can't open $pidFile: $!\n";
print
PIDFILE $tshark_pid;
close
PIDFILE;
while
() {
my ($called,$caller,$name) =
split("#",$_);
# do whatever I want with the variables
here ...
my $thr = threads->new(
\&processit,$called,$caller,$name)->detach();
}
sub
processit {
my ($lcalled,$lcaller,$lname) = @_;
#local client
$lname =~ s/'/''/g;
$log->warning("Repondeur!
Called : $lcalled, Caller : $lcaller, Name :$lname");
$log->warning("INSERT OR
REPLACE INTO auderix VALUES ('$lcalled', '$lcaller','''$lname''')");
my $db =
DBI->connect("dbi:SQLite:/var/lib/asterisk/agi-bin/auderix.db",
"", "",{RaiseError => 1, AutoCommit => 1});
$db->do("INSERT OR REPLACE INTO
auderix VALUES ('$lcalled', '$lcaller','''$lname''')") or
$exception->warning("ERROR a l'insertion de INSERT OR REPLACE INTO
auderix VALUES ('$lcalled', '$lcaller','$lname')");;
}
mkdir /var/log/auderix
touch /var/log/auderix/auderix-analyzer-access.log
Now we
start the service:
/etc/init.d/auderix
start
vi
/var/lib/asterisk/agi-bin/Auderixrequester.pl
chmod
a+x Auderixrequester.pl
copy and
paste inside content below:
#!/usr/bin/perl
use DBI;
use
Error qw(:try);
use
POSIX qw(setsid);
use
Log::Dispatch;
use
Log::Dispatch::File;
use
File::Spec;
use
Date::Format;
use
Asterisk::AGI;
#my
$caller = $ARGV[0];
$AGI =
new Asterisk::AGI;
my
%input = $AGI->ReadParse();
my
$caller = $AGI->get_variable("CALLERID(num)");
my $db =
DBI->connect("dbi:SQLite:/var/lib/asterisk/agi-bin/auderix.db",
"", "",
{RaiseError
=> 1, AutoCommit => 1});
my $all
= $db->selectall_arrayref("SELECT * FROM auderix where
callernum='$caller'");
foreach
my $row (@$all) {
my ($callednum,$callernum,$calledname)
= @$row;
if (length($callernum) == 9 )
{
$callernum="0".$callernum;
}
elsif (length($callernum) > 9 )
{
$callernum="+".$callernum;
}
#$AGI->set_variable("callernum", $callernum);
#$AGI->set_variable("callednum", $callednum);
print "SET VARIABLE callernum
\"$callernum\"\n";
print "SET VARIABLE callednum
\"$callednum\"\n";
$db->do("DELETE FROM auderix
where callednum='$callednum'");
}
Check
that process auderix is running by using command below:
ps aux|
grep tsh
you
should see
tshark
-l -T fields -e qsig.privateNumberDigits -e q931.calling_party_number.digits -e
qsig.na.namePresentationAllowedSimple -Y qsig.privateNumberDigits -E occurrence
l -E separator #
Into
/etc/asterisk/ooh323.conf
[general]
;The
port asterisk should listen for incoming H323 connections.
;Default
- 1720
port=1720
;The
dotted IP address asterisk should listen on for incoming H323
;connections
;Default
- tries to find out local ip address on it's own
bindaddr=0.0.0.0
;This
parameter indicates whether channel driver should register with
;gatekeeper
as a gateway or an endpoint.
;Default
- no
;gateway=no
; See
https://wiki.asterisk.org/wiki/display/AST/IP+Quality+of+Service for a
description of these parameters.
tos_audio=ef ; Sets TOS for RTP audio packets.
cos_audio=5 ; Sets 802.1p priority for RTP
audio packets.
;Whether
asterisk should use fast-start and tunneling for H323 connections.
;Default
- yes
faststart=yes
;h245tunneling=yes
;Whether
media wait for connect
;Default
- No
;mediawaitforconnect=yes
;H323-ID
to be used for asterisk server
;Default
- Asterisk PBX
h323id=Anonyme
;e164=none
;CallerID
to use for calls
;Default
- Same as h323id
;callerid=asterisk
;Whether
this asterisk server will use gatekeeper.
;Default
- DISABLE
;gatekeeper
= DISCOVER
;gatekeeper
= a.b.c.d
gatekeeper
= DISABLE
;Location
for H323 log file
;Default
- /var/log/asterisk/h323_log
;tracelevel=20
;logfile=/var/log/asterisk/h323_log
disallow=all
allow=alaw
canreinvite=no
dtmfmode=rfc2833
context=from-h323
[Avaya]
language
= fr
country
= fr
type=friend
host=10.147.9.64
port=1720
disallow=all
allow=alaw
canreinvite=no
;h245tunneling=yes
;dtmfmode=rfc2833
;dtmfmode=h245signal
As you
can see incoming calls coming from ooh323 will goes to extensions.conf into
from-h323 context, into this one we’ll call ParisOfficeVoicemail
[from-h323]
include
=> ParisOfficeVoicemail
Into
/etc/asterisk/extensions.conf create a context that will be dialed by from-h323
context in my case:
[ParisOfficeVoicemail]
exten
=> 46750,1,Progress()
exten
=> 46750,n,Wait(1) ;//Important because Asterisk is faster than Tshark so it
let time to perl script using tshark to write into database
exten
=> 46750,n,AGI(Auderixrequester.pl)
exten
=> 46750,n,NoOp(Callernum: ${callernum})
exten
=> 46750,n,NoOp(Callednum: ${callednum})
exten
=> 46750,n,Set(CHANNEL(language)=fr)
exten
=> 46750,n,Set(CALLERID(num)=${callernum})
exten
=> 46750,n,GotoIf($["${callednum}" = ""]?2000)
exten
=> 46750,n,GotoIf($["${CALLERID(num)}" = ""]?1000)
exten
=> 46750,n,VoiceMail(${callednum}@ParisOfficeVoiceMail,su)
exten
=> 46750,n,Hangup()
exten
=> 46750,1000,Set(CALLERID(name)="numéro masqué")
exten
=> 46750,n,VoiceMail(${callednum}@ParisOfficeVoiceMail,su)
exten
=> 46750,2000,PlayBack(vm-goodbye)
exten
=> 46750,n,system(/bin/echo "There is an issue with TSHARK please
restart it" | /usr/bin/mail -s "TSHARK ISSUE" cyril.constantin@gmail.com)
exten
=> 46750,n,system(/etc/init.d/auderix restart)
exten
=> 46750,n,Hangup()
If you
are using realtime for storing your voicemail config then create an entry into
this mysql table where context would be “ParisOfficeVoicemail”
Mailbox
: Your Avaya IP Phone number so in my case 40053
Fullname:
Cyril CONSTANTIN
Attach:yes
Attachfmt:wav49
Deletevoicemail:yes
Sendvoicemail:no
Now on
Avaya you should have created a route to go to Asterisk, in our case we have
setup 46XXX
So it
will use IP trunk 62, for more details on how to create IP trunk through H.323
to Asterisk check on my blog there is all details.
We
create a hunt group that would be assigned to a coverage path, which will be
attributed to IP Phone station.
We need
to configure our voicemail config file which will generate an email with
subject and voicemail in attachment vi /etc/asterisk/voicemail.conf:
[general]
format=wav49|gsm|wav
serveremail=asterisk@pt0asterisk01.lenumero.local
attach=no
skipms=3000
maxsilence=10
silencethreshold=128
maxlogins=3
charset=UTF-8
fromstring=Serveur
Vocal
emailsubject = Vous avez un nouveau message d'une durée
de ${VM_DUR} de la part du ${VM_CALLERID}
emailbody = ${VM_NAME}, \n\nVous avez reçu un nouveau
message d'une durée de ${VM_DUR} \nde la part de
${VM_CALLERID}.\n\n\n\n\n\t\t\t\t\t\t\t\t\t\t Votre serveur vocal\n
attachfmt=wav49
endvoicemail=no
delete=no
I’ll let
you configure your mail server properly.
Make a
test call from another Avaya IP Phone to the Avaya phone using coverage path
100 you call should go to Asterisk and into the console you should see something like below (use asterisk –r)
[Sep 3 10:44:28] -- Executing [46750@from-h323:1]
Wait("OOH323/AvayaSpecificDTMF-2270", "1") in new stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:2]
AGI("OOH323/AvayaSpecificDTMF-2270", "Auderixrequester.pl") in new
stack
[Sep 3 10:44:29] -- Launched AGI Script
/var/lib/asterisk/agi-bin/Auderixrequester.pl
[Sep 3 10:44:29] ERROR[18992][C-00000905]:
utils.c:1393 ast_carefulwrite: write() returned error: Broken pipe
[Sep 3 10:44:29] --
AGI Script Auderixrequester.pl completed,
returning 0
[Sep 3 10:44:29] -- Executing [46750@from-h323:3] NoOp("OOH323/AvayaSpecificDTMF-2270",
"Callernum:
44241") in new stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:4]
NoOp("OOH323/AvayaSpecificDTMF-2270", "Callednum: 40053") in new stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:5] Set("OOH323/AvayaSpecificDTMF-2270",
"CHANNEL(language)=fr") in new stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:6]
Set("OOH323/AvayaSpecificDTMF-2270", "CALLERID(num)=44241")
in new stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:7] GotoIf("OOH323/AvayaSpecificDTMF-2270",
"0?2000") in new stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:8]
GotoIf("OOH323/AvayaSpecificDTMF-2270", "0?1000") in new
stack
[Sep 3 10:44:29] -- Executing [46750@from-h323:9]
VoiceMail("OOH323/AvayaSpecificDTMF-2270", "40053@ParisOfficeVoiceMail,su")
in new stack
[Sep 3 10:44:30] WARNING[18992][C-00000905]:
app_voicemail.c:6350 leave_voicemail: No entry in voicemail config file for
'40053'
[Sep 3 10:44:30] -- Executing [46750@from-h323:10] Hangup("OOH323/AvayaSpecificDTMF-2270",
"") in new stack
[Sep 3 10:44:30]
== Spawn extension (from-h323, 46750, 10) exited non-zero on
'OOH323/AvayaSpecificDTMF-2270'
pt0asterisk01*CLI>
In all case you will have maybe to change a little bit some piece regarding your needs regarding your country digit lengths because it was based on French digits length and international format so it require a little bit of knowledge to edit PERL or bash script if needed. Also this article has been done with using Debian 8 and tshark 1.12.1, I know that with older release of tshark it was need into auderix-analyzer to use a different command like below:
my $tshark_pid = open (TSHARK,"tshark -l -T fields -e qsig.privateNumberDigits -e q931.calling_party_number.digits -e qsig.na.namePresentationAllowedSimple -R qsig.privateNumberDigits -E separator=#|");
In all case prepare your routing on Avaya, set H323 trunk between Avaya and Asterisk then on linux shell use tshark command manually to see what you get from Avaya normally you should get something under this format:
40053#44241#Cyril, CONSTANT
Called extension#Calling extension#Called Name
So you could move forward on setting all scripts above.
Enjoy it and don't hesitate to ask me question and I'll try to do my best to help you.
Best Regards