FreePBX. Настройка на Asterisk за e-mail уведомления за пропуснати входящи повиквания в опашката.

FreePBX. Настройка на Asterisk за e-mail уведомления за пропуснати входящи повиквания в опашката.
IP ATC Asterisk — мощно решение в областта на IP телефонията. Уеб интерфейсът FreePBX, създаден за Asterisk, значително улеснява конфигурацията и намалява бариерата за влизане в системата.
Ако можете да измислите каквато и да е задача, свързана с IP телефонията, почти сигурно може да бъде реализирана в Asterisk. Но бъдете сигурни, че ще ви е нужно упорство и търпение.

Пред нас стоеше задачата да настроим e-mail известия за пропуснати повиквания. По-точно, да уведомяваме чрез e-mail за случаите, когато входящо повикване е преминало в опашка, но никой (от агентите) не е отговорил на това входящо повикване.

Учудващо, не открихме стандартни средства за решаване на тази задача във FreePBX. Как решихме тази задача, ще разкажа по-долу.

Предговор

Преди да решим задачата "в лоб", разбира се, потърсихме информация в интернет, но не намерихме готово решение (възможно е да не сме търсили добре, но каквото и да е...).

Не разполагаме с много умения за работа директно в Asterisk, така че предложеното решение тук., не беше напълно осмислено и беше отхвърлено.

Хареса ни решението, предложено от тук., макар и да не проработи. Оттук подчертахме, че работата в Asterisk трябва да бъде в контекста на опашките [ext-queues]. И тъй като работим с FreePBX, трябва да работим в конфигурационния файл „extensions_override_freepbx.conf“. Обърнахме внимание, че е удобно да се "похващат пропуснати повиквания" преди събитието hangupcall (завършване на повикването).
Прочитайки обсъждането на тук., се роди идея, че трябва да филтрираме в CDR променливата „Disposition“ по всички агенти в опашката. А след прочитане на тази информацията, се оформиха съвсем конкретни стъпки за решаване на поставената задача.

Какво имаме:

Имаме FreePBX 13.0.197, който използва Asterisk 13.12.1. Версия на ОС SHMZ release 6.6 (Final). Дистрибуцията е базирана на CentOS.

В Asterisk е настроен IVR (гласово меню), разпределящ входящите повиквания на различни опашки (Queues). На всяка опашка са назначени агенти.

Теория

Какво се случва в Asterisk

Когато в Asterisk постъпи входящо повикване, затова повикване попада на IVR. Звънецът прави избор, натискайки определена цифра на телефона, и попада в определена опашка. След това на всички свободни агенти в опашката едновременно постъпва повикване.

За да разберем по-добре какво се случва в този момент и какво се случва след това, ще се обърнем към Report CDR (Рис.1).

FreePBX. Настройка на Asterisk за e-mail уведомления за пропуснати входящи повиквания в опашката.
Рис.1

Когато входящият повик е попаднал в опашката, стойността на променливата «Disposition» на всички агенти е станала равна на «NO ANSWER», ако агентите в този момент не са били ангажирани. Променливата «Disposition» може да приеме и други стойности (вж. https://asterisk-pbx.ru/wiki/asterisk/cf/cdr), освен стойността «ANSWERED». В момента, когато един от агентите отговаря на входящото повикване, стойността на променливата «Disposition» на този агент става равна на «ANSWERED».
От Report CDR може да се забележи, че когато повикването е преминало в опашката (в колоната App стойността става равна на «Queue»), всички събития се появяват с идентичен «uniqueid» (колонка System).

Накратко за CDR

Важно е да разберем какво е CDR и в кой момент в CDR се записват данните, които наблюдаваме в Report CDR. CDR, относно операционната система, е база данни, в която Asterisk записва подробен отчет за повикванията (вж. https://asterisk-pbx.ru/wiki/asterisk/cf/cdr). В нашия случай това е база под името asteriskcdrdb, която се намира в mysql. Чрез опити установихме, че данните за повикване с определен «uniqueid» се записват в asteriskcdrdb не веднага след възникването на дадено събитие, а след събитието hangupcall (приключване на повикването).

Принцип на работа на създаденото решение

Тъй като имаме повече познания по bash, отколкото по Asterisk, основната идея е следната. Преди събитието hangupcall да се извика bash-скрипт. В този скрипт трябва да се предадат 3 параметъра. Първият параметър е «uniqueid», за филтриране на данните, получени от CDR. Вторият параметър е «CALLERID(num)» (номер на звонилния), за да знаем на кого да се обадим повторно. Третият параметър е «NODEST» (номер на опашката), в която е постъпило повикването, за да знаем по какво е било повикването и на кого да изпратим e-mail уведомление за пропуснатото повикване.
Bash-скриптът трябва да се свърже с базата asteriskcdrdb в mysql и да вземе всички стойности на променливата «Disposition» с определен «uniqueid». От получените данни трябва да се изключат стойностите: «NO ANSWER», «BUSY», «FAILED», «UNKNOWN». В резултат ще останат или «ANSWERED» — на входящото повикване е отговорено, или изобщо нищо — пропуснато повикване.

След това, ако повикването е пропуснато, скриптът трябва да изпрати e-mail уведомление.
Предварително искам да подчертая важен момент. Asterisk изпълнява командите последователно, изчаквайки тяхното изпълнение (което е логично). Но ще извикаме bash-скрипта преди да се изпълни командата hangupcall. По този начин, в момента на непосредственото изпълнение на скрипта, в CDR все още няма да има информация за търсения от нас «uniqueid». За решаване на този проблем ще извикаме bash-скрипта с параметър «&», за да може Asterisk веднага да премине към изпълнението на следващата стъпка, т.е. hangupcall. А в самото начало на bash-скрипта ще установим малко забавяне по време, за да дадем време на Asterisk да въведе данните с интересуващия ни «uniqueid» в CDR.

Практика

Преди да преминем към настройката на Asterisk и създаването на bash-скрипта, е необходимо да настроим изпращането на e-mail уведомления. За целта ще използваме утилитата postfix.

Настройка на postfix

Имаме пощенски домейн «lucky.ru», разположен в Яндекс. Ще настроим postfix в режим на smtp-клиент и ще изпращаме писма от акаунта asterisk@lucky.ru.
За основа е взето решението оттук: https://www.dmosk.ru/miniinstruktions.php?mini=postfix-over-yandex.

Първо ще инсталираме/обновим/проверим наличието на пакети:

yum install postfix
yum install mailx
yum install cyrus-sasl cyrus-sasl-lib cyrus-sasl-plain

Не е необходимо да изтриваме основния конфигурационен файл на postfix «/etc/postfix/main.cf», а вместо това да създадем резервно копие:

cp /etc/postfix/main.cf /etc/postfix/main.cf.sav

Редактираме файла «/etc/postfix/main.cf» и го преобразуваме в следния вид:

nano /etc/postfix/main.cf
#####################
relayhost =
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/private/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_sasl_type = cyrus
smtp_sasl_mechanism_filter = login
smtp_sender_dependent_authentication = yes
sender_dependent_relayhost_maps = hash:/etc/postfix/private/sender_relay
smtp_generic_maps = hash:/etc/postfix/generic
smtp_tls_CAfile = /etc/postfix/ca.pem
smtp_use_tls = yes
smtputf8_autodetect_classes = all
#####################

Не всяка ред в «/etc/postfix/main.cf» може да бъде коментирана. Коментарите в някои редове не се определят от парсера и преминават към обработка, което води до грешки. По-добре е да се откажете от коментари в този файл. Можете да експериментирате с това, като стартирате в съседния прозорец «tail -f /var/log/messages».

Искам да подчертая реда «smtputf8_autodetect_classes = all». Това настроежда utf-8 по подразбиране, което позволява използването на кирилица както в тялото на писмото, така и в темата на писмото без допълнителни манипулации (Виж. http://www.postfix.org/SMTPUTF8_README.html).

Да създадем каталог за конфигурационни файлове:

mkdir /etc/postfix/private

Редактирайте файла «/etc/postfix/private/sender_relay». В него трябва да укажете на кой SMTP сървър да се отнасяте при използването на нашия имейл домейн:

nano /etc/postfix/private/sender_relay
#####################
@lucky.ru smtp.yandex.ru
#####################

Редактирайте файла «/etc/postfix/private/sasl_passwd». В него ще посочим имейл адреса, който ще използваме за изпращане на писма, а също така логина и паролата на тази учетна запис (логина и паролата посочваме с двоеточие):

nano /etc/postfix/private/sasl_passwd
#####################
asterisk@lucky.ru asterisk@lucky.ru:password_asterisk
#####################

Редактирайте файла «/etc/postfix/generic». В него ще формулираме правилата за замяна на изходящия адрес (вижте. https://wiki.merionet.ru/ip-telephoniya/30/postfix-nastrojka-otpravki-pochty-v-asterisk/):

nano /etc/postfix/generic
#####################
root asterisk@lucky.ru
root@localhost asterisk@lucky.ru
root@localhost.localdomain asterisk@lucky.ru
root@freepbx asterisk@lucky.ru
root@freepbx.localdomain asterisk@lucky.ru
root@asterisk asterisk@lucky.ru
root@asterisk.localdomain asterisk@lucky.ru
asterisk asterisk@lucky.ru
asterisk@localhost asterisk@lucky.ru
asterisk@localhost.localdomain asterisk@lucky.ru
asterisk@freepbx asterisk@lucky.ru
asterisk@freepbx.localdomain asterisk@lucky.ru
asterisk@asterisk asterisk@lucky.ru
asterisk@asterisk.localdomain asterisk@lucky.ru
root@localdomain.localdomain asterisk@lucky.ru
#####################

Началният изходящ адрес зависи от съдържанието на «/etc/hosts» и «/etc/hostname», а също така и от потребителя, който ще изпрати писмото. Т.е. макар да използваме SMTP клиент и изпращаме писма от asterisk@lucky.ru, все пак в адреса на подателя Postfix първоначално ще постави «нещо свое» и това трябва да бъде коригирано с правилата от този конфигурационен файл.

Ще ви покажа съдържанието на моя файл «/etc/hosts»:

cat /etc/hosts
#####################
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 asterisk.localdomain
127.0.0.1 localhost.localdomain localhost
::1 asterisk localhost localhost6
#####################

Важно е сървърът да има домейн (стойност след точката), защото утилитата mail «търси» името на домейна в «/etc/hosts» и ако «не го намери» веднага, ще продължи да го търси още няколко минути и едва след това ще изпрати писмото. Т.е. ако домейнът не е указан, писмото ще бъде изпратено с забавяне от няколко минути.

Ще ви покажа съдържанието на моя файл «/etc/hostname»:

cat /etc/hostname
#####################
asterisk
#####################

След това е необходимо да преобразуваме създадените конфигурационни файлове в индексирани бази данни, за целта изпълняваме следната команда:

postmap /etc/postfix/generic && postmap /etc/postfix/private/{sasl_passwd,sender_relay}

След това трябва да свалим и поставим на сървъра сертификата smtp.yandex.ru, за целта изпълняваме следната команда:

openssl s_client -starttls smtp -crlf -connect smtp.yandex.ru:25 > /etc/postfix/ca.pem

Но след като на екрана се появят техническите данни, екипът ще продължи да "застива". Натиснете Ctrl+C, за да прекратите това.

Сега ръчно ще премахнем целия ненужен текст от получения файл и ще оставим само сертификата. Трябва да се получи нещо подобно:

nano /etc/postfix/ca.pem
#####################
-----BEGIN CERTIFICATE-----
MIIGazCCBVOgAwIBAgIQcUU9mJXW4OUs5Gf0JfLtsjANBgkqhkiG9w0BAQsFADBf
...
nRG0DfdqYIuPGApFORYe
-----END CERTIFICATE-----
#####################

И накрая, ще рестартираме postfix:

service postfix restart

Изпращаме тестово писмо:

echo "Това е съдържанието на писмото" | mail -s "Това е темата" admin@lucky.ru

admin@lucky.ru — получателят

С това настройката на postfix приключва.

Пишем bash скрипт

Създаваме директория за съхранение на bash скрипта (тук, където на кого му е по-удобно):

mkdir /home/asterisk/scripts

Създаваме файла на bash скрипта:

touch /home/asterisk/scripts/noanswer.sh

Даваме на файла на скрипта права за изпълнение:

chmod +x /home/asterisk/scripts/noanswer.sh

Ако имате съмнения относно правата на файла, можете временно да дадете пълен достъп до файла за отстраняване на грешки. Но това е "небезопасно".

chmod 777 /home/asterisk/scripts/noanswer.sh

Текст на bash скрипта:

nano /home/asterisk/scripts/noanswer.sh
#####################
#! /bin/bash

sleep 7

res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"

answer=`mysql -u freepbxuser -pPassword_freepbxuser -D asteriskcdrdb -B -N -e "$res_sql" | grep -E -v "NO ANSWER|BUSY|FAILED|UNKNOWN" | head -n 1`

error_kod=0
if [ "$answer" != "ANSWERED" ]
then

 case $3 in
 68800)
 address="big_boss@lucky.ru"
 subject="по важен въпрос"
 ;;
 63100)
 address="debian@lucky.ru"
 subject="по въпросите на linux debian"
 ;;
 63200)
 address="windows@lucky.ru"
 subject="по въпросите на windows"
 ;;
 63300)
 address="freebsd@lucky.ru"
 subject="по въпросите на freebsd"
 ;;
 63400)
 address="ubuntu@lucky.ru"
 subject="по въпросите на linux ubuntu"
 ;;
 63500)
 address="centos@lucky.ru"
 subject="по въпросите на linux centos"
 ;;
 *)
 address="admin@lucky.ru"
 error_kod=1
 ;;
 esac

 case $error_kod in
 0)
 echo "Пропуснато обаждане от абонат $2, звънял $subject." | mail -s "Пропуснато обаждане от $2" $address
 echo "Пропуснато обаждане за $address от абонат $2, звънял $subject. uid=$1" | mail -s "Пропуснато обаждане от $2" admin@lucky.ru
 ;;
 1)
 echo "Пропуснато обаждане от $2. Опашката е неизвестна. uid=$1" | mail -s "Пропуснато обаждане от $2" admin@lucky.ru
 ;;
 esac

fi
#####################

Кратко обяснение на скрипта:
«sleep 7»:

Това е забавянето по време, за което споменах по-рано. Имаме установено забавяне от 7 секунди. Въпреки това, мисля, че дори и една секунда ще е напълно достатъчна.

«res_sql="SELECT disposition FROM cdr WHERE uniqueid = '$1'"»:

Запитването в mysql сме изнесли в отделна променлива за удобство.

Следва да направим запитване в mysql и да филтрираме получените данни. Премахваме всички опции с изключение на „ANSWERED“, ако такава изобщо съществува. Ако обаче има повече от едно значение „ANSWERED“, трябва да оставим само едно. В края в променливата „answer“ ще получим или „ANSWERED“, или „“.
Ако стойността на променливата „answer“ не е равна на „ANSWERED“, то това е пропуснато обаждане. В зависимост от номера на опашката, с помощта на оператора case ще зададем адреса, на когото точно трябва да изпратим e-mail известие, и какво да пишем в това съобщение (променливата част на съобщението).

Следва вариант, при който опашката е зададена в Asterisk, но не е описана в скрипта. В този случай admin@lucky.ru ще получи имейл, че опашката не е известна на скрипта.

Ако обаче опашката е описана, ще бъде изпратено писмо до назначеното място и дублиращо писмо на admin@lucky.ru с указание „uniqueid“, за да може да се проследят събитията по това обаждане, в случай на необходимост.

На това скриптът завършва.

Ще отбележа, че за свързване с mysql използвахме потребителско име и парола, които предварително научихме. В FreePBX, за да разберете потребителското име на Asterisk в mysql, изпълнете следната команда:

cat /etc/amportal.conf | grep AMPDBUSER

А за да разберете паролата на Asterisk в mysql, изпълнете следната команда:

cat /etc/amportal.conf | grep AMPDBPASS

Настройка на Asterisk

Използваме FreePBX. В FreePBX има различни типове конфигурационни файлове (виж. https://asterisk-pbx.ru/wiki/freepbx/files), някои от тях FreePBX презаписва при презареждане, а някои не (те се наричат custom), тъй като са специално предназначени за потребителя.

Ще работим с конфигурационния файл „extensions_override_freepbx.conf“, тъй като той принадлежи към типа custom.

Първо, нека се уверим, че в файла „/etc/asterisk/extensions.conf“ е свързан файлът „extensions_override_freepbx.conf“. За целта изпълнете следната команда:

cat /etc/asterisk/extensions.conf | grep extensions_override_freepbx.conf
#####################
#include extensions_override_freepbx.conf
#####################

Редактирайте файла „/etc/asterisk/extensions_override_freepbx.conf“ и го приведете в следния вид:

nano /etc/asterisk/extensions_override_freepbx.conf
#####################
[ext-queues]

exten => h,1,System(/home/asterisk/scripts/noanswer.sh ${CDR(uniqueid)} ${CALLERID(num)} ${NODEST} &)
exten => h,2,Macro(hangupcall,)
#####################

Както вече споменах, символът «&» в края е задължителен. Тъй като ще работим с bash-скрипт, който обработва CDR данни директно от базата mysql, а тези данни се записват в mysql само след изпълнението на «exten => h,2,Macro(hangupcall,)», е необходимо да не чакаме приключването на bash-скрипта, а да преминем към следващата стъпка в Asterisk. А самият bash-скрипт би трябвало да съдържа времево забавяне преди изпълнението на основната си част.

За да влязат в сила измененията в конфигурационния файл «/etc/asterisk/extensions_override_freepbx.conf», е необходимо да се рестартира ядрото на Asterisk с следната команда:

/usr/sbin/asterisk -rx "core restart now"

Това трябва да се направи след като bash-скриптът бъде създаден.

Заключение

Вероятно това е 1001-ят начин за „улов на пропуснати обаждания“ в Asterisk. Споделете в коментарите как вие решавате тази задача. И какво, според вас, може да бъде подобрено/променено/оптимизирано. Ще бъдем благодарни за конструктивни идеи.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster