FreePBX. Configuração do Asterisk para notificações por e-mail sobre chamadas perdidas em filas

FreePBX. Configuração do Asterisk para notificações por e-mail sobre chamadas perdidas em filas
O IP ATC Asterisk é uma poderosa combinação no campo da telefonia IP. A interface web FreePBX, desenvolvida para o Asterisk, simplifica significativamente a configuração e reduz a barreira de entrada no sistema.
Se você consegue imaginar qualquer tarefa relacionada à telefonia IP, quase certamente isso pode ser realizado no Asterisk. Mas tenha certeza de que será necessário persistência e paciência da sua parte.

Enfrentamos a tarefa de configurar notificações por e-mail sobre chamadas perdidas. Mais especificamente, notificar por e-mail nos casos em que uma chamada recebida foi para a fila, mas ninguém (dos agentes) respondeu a essa chamada.

Surpreendentemente, não encontramos recursos nativos para resolver essa tarefa no FreePBX. Como resolvemos esse problema, contarei a seguir.

Prefácio

Antes de resolver a tarefa diretamente, certamente buscamos informações na internet, mas não encontramos uma solução pronta (talvez não tenhamos buscado bem, mas o que podemos fazer...).

As habilidades de trabalho diretamente no Asterisk não são tantas quanto gostaríamos, então a solução proposta aqui, não foi totalmente compreendida e foi descartada.

Gostei da solução proposta por aqui, embora não tenha funcionado. Por isso, destacamos que é necessário trabalhar no Asterisk no contexto das filas [ext-queues]. E como estamos trabalhando no FreePBX, o trabalho deve ser feito no arquivo de configuração ‘extensions_override_freepbx.conf’. Notamos que ‘capturar chamadas perdidas’ é conveniente antes do evento hangupcall (fim da chamada).
Ao ler a discussão sobre aqui, surgiu a ideia de que precisamos filtrar a variável ‘Disposition’ no CDR para todos os agentes na fila. E após a leitura de artigo. Mas, como mencionado anteriormente, ao tentarmos aplicá-lo diretamente no blockchain, surgem limitações técnicas. Aqui está um exemplo de implementação de teste do protocolo em um contrato inteligente EOS e sua parte mais importante — a verificação do share publicado pelo participante: as informações foram formados passos bem concretos para resolver a tarefa proposta.

O que temos:

Temos FreePBX 13.0.197, que usa Asterisk 13.12.1. A versão do SO é SHMZ release 6.6 (Final). A distribuição é baseada no CentOS.

No Asterisk, foi configurado um IVR (menu de voz) que distribui chamadas recebidas para diferentes filas. A cada fila, são designados agentes, ou seja, operadores.

Teoria

O que acontece no Asterisk

Quando uma chamada recebida chega ao Asterisk, ela vai para o IVR. O chamador faz uma escolha, pressionando um número específico no telefone, e vai para uma fila específica. Depois disso, todos os agentes livres da fila recebem a chamada ao mesmo tempo.

Para entender melhor o que acontece nesse momento e o que acontece a seguir, vamos nos referir ao Report CDR (Fig. 1).

FreePBX. Configuração do Asterisk para notificações por e-mail sobre chamadas perdidas em filas
Fig. 1

Quando uma chamada recebida entra na fila, o valor da variável "Disposition" para todos os agentes se torna "NO ANSWER", caso eles estejam desocupados naquele momento. A variável "Disposition" pode assumir outros valores (veja https://asterisk-pbx.ru/wiki/asterisk/cf/cdr), além do valor "ANSWERED". No momento em que um dos agentes atende a chamada recebida, o valor da variável "Disposition" desse agente se torna "ANSWERED".
No Report CDR, é possível notar que quando a chamada é transferida para a fila (na coluna App, o valor se torna "Queue"), todos os eventos aparecem com o mesmo "uniqueid" (coluna System).

Sobre CDR

É importante entender o que é CDR e em qual momento os dados que observamos no Report CDR são registrados. O CDR, em relação ao sistema operacional, é um banco de dados onde o Asterisk registra um relatório detalhado de chamadas (veja https://asterisk-pbx.ru/wiki/asterisk/cf/cdr). No nosso caso, trata-se de um banco de dados chamado asteriskcdrdb, que está no mysql. Através de testes, determinamos que os dados sobre uma chamada com determinado "uniqueid" são registrados no asteriskcdrdb não imediatamente após a ocorrência de algum evento, mas sim após o evento hangupcall (finalização da chamada).

Princípio de funcionamento da solução criada

Como temos mais conhecimento em bash do que em Asterisk, a ideia principal ficou assim. Antes do evento hangupcall, um script em bash deve ser chamado. Para esse script, devem ser passados 3 parâmetros. O primeiro parâmetro é "uniqueid", para filtrar os dados obtidos do CDR. O segundo parâmetro é "CALLERID(num)" (número do chamador), para saber a quem retornar a ligação. O terceiro parâmetro é "NODEST" (número da fila), para saber sobre qual assunto a chamada foi e a quem enviar a notificação por e-mail sobre a chamada perdida.
O script bash deve se conectar ao banco asteriskcdrdb no mysql e obter todos os valores da variável "Disposition" com um determinado "uniqueid". Dos dados obtidos, deve-se excluir os valores: "NO ANSWER", "BUSY", "FAILED", "UNKNOWN". No resultado, permanecerão "ANSWERED" — se a chamada recebida foi atendida, ou nada — se foi uma chamada perdida.

Em seguida, se a chamada for considerada perdida, o script deve enviar uma notificação por e-mail.
Adiantando um ponto importante. O Asterisk executa comandos sequencialmente, aguardando a sua conclusão (o que, de fato, é lógico). E chamaremos o script bash antes que o comando hangupcall seja executado. Assim, no momento em que o script for executado, ainda não haverá informações sobre o «uniqueid» que estamos procurando no CDR. Para resolver esse problema, chamaremos o script bash com o parâmetro «&», para que o Asterisk passe imediatamente para a próxima etapa, ou seja, hangupcall. E dentro do script bash, desde o início, estabeleceremos um pequeno atraso para permitir que o Asterisk registre os dados do «uniqueid» que nos interessa no CDR.

Prática

Antes de passarmos para a configuração do Asterisk e a criação do script bash, precisamos configurar o envio de notificações por e-mail. Para isso, usaremos a ferramenta postfix.

Configuração do postfix

Temos um domínio de e-mail «lucky.ru», localizado no Yandex. Configuraremos o postfix em modo de cliente SMTP e enviaremos e-mails da conta asterisk@lucky.ru.
A base é a solução a partir daqui: https://www.dmosk.ru/miniinstruktions.php?mini=postfix-over-yandex.

Primeiro, instalaremos/atualizaremos/verificaremos a presença dos pacotes:

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

Não vamos sobrescrever o arquivo de configuração principal do postfix «/etc/postfix/main.cf», mas faremos uma cópia de segurança dele:

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

Editaremos o arquivo «/etc/postfix/main.cf» e o ajustaremos da seguinte forma:

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
#####################

Nem todas as linhas em «/etc/postfix/main.cf» podem ser comentadas. Comentários em algumas linhas não são reconhecidos pelo parser e são processados, o que resulta em erros. É melhor evitar comentários dentro desse arquivo. Você pode experimentar isso executando «tail -f /var/log/messages» em outra janela.

Destaco a linha «smtputf8_autodetect_classes = all». Esta configuração ativa utf-8 por padrão, permitindo o uso de caracteres cirílicos tanto no corpo do e-mail quanto no assunto, sem manipulações adicionais (Ver. http://www.postfix.org/SMTPUTF8_README.html).

Vamos criar um diretório para os arquivos de configuração:

mkdir /etc/postfix/private

Editando o arquivo «/etc/postfix/private/sender_relay». Nele, precisamos indicar a qual servidor smtp devemos nos referir ao usar nosso domínio de e-mail:

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

Editando o arquivo «/etc/postfix/private/sasl_passwd». Nele, indicaremos o endereço de e-mail que utilizaremos para enviar mensagens, assim como o login e a senha dessa conta (login e senha separados por dois pontos):

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

Editando o arquivo «/etc/postfix/generic». Nele, escreveremos as regras para substituir o endereço de saída (veja. 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
#####################

O endereço de saída original depende do conteúdo de «/etc/hosts» e «/etc/hostname», assim como do nome do usuário que irá enviar o e-mail. Ou seja, apesar de estarmos usando um cliente smtp e enviando e-mails de asterisk@lucky.ru, o postfix inicialmente colocará «algo próprio» no endereço de remetente e isso precisa ser corrigido com as regras deste arquivo de configuração.

Aqui está o conteúdo do meu arquivo «/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
#####################

É importante que o servidor tenha algum domínio (valor após o ponto), pois a ferramenta mail «procura» o nome do domínio em «/etc/hosts» e se «não o encontrar» imediatamente, continuará a busca por mais alguns minutos e só então enviará o e-mail. Ou seja, se o domínio não estiver registrado, o e-mail será enviado com um atraso de alguns minutos.

Aqui está o conteúdo do meu arquivo «/etc/hostname»:

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

Em seguida, é necessário converter os arquivos de configuração criados para bancos de dados indexados, para isso, execute o seguinte comando:

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

Em seguida, precisamos baixar e instalar no servidor o certificado smtp.yandex.ru, para isso, execute o seguinte comando:

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

Mas depois que as informações técnicas aparecerem na tela, a equipe 'continuará a travar'. Pressione Ctrl+C para interrompê-la.

Agora, vamos remover manualmente todo o lixo do arquivo resultante e deixar apenas o certificado. Deve ficar algo parecido com:

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

E finalmente, vamos reiniciar o postfix:

service postfix restart

Enviando um e-mail de teste:

echo "Este é o corpo do e-mail" | mail -s "Este é o assunto" admin@lucky.ru

admin@lucky.ru — endereço de destino

Com isso, a configuração do postfix está concluída.

Escrevendo um script bash

Criando um diretório para armazenar o script bash (aqui, onde você preferir):

mkdir /home/asterisk/scripts

Criando o arquivo do script bash:

touch /home/asterisk/scripts/noanswer.sh

Dando permissão de execução ao arquivo do script:

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

Se houver dúvidas sobre as permissões do arquivo, para fins de depuração, pode-se conceder acesso total ao arquivo. Mas isso é 'inseguro'.

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

Texto do script 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="sobre um assunto importante"
 ;;
 63100)
 address="debian@lucky.ru"
 subject="sobre assuntos do linux debian"
 ;;
 63200)
 address="windows@lucky.ru"
 subject="sobre assuntos do windows"
 ;;
 63300)
 address="freebsd@lucky.ru"
 subject="sobre assuntos do freebsd"
 ;;
 63400)
 address="ubuntu@lucky.ru"
 subject="sobre assuntos do linux ubuntu"
 ;;
 63500)
 address="centos@lucky.ru"
 subject="sobre assuntos do linux centos"
 ;;
 *)
 address="admin@lucky.ru"
 error_kod=1
 ;;
 esac

 case $error_kod in
 0)
 echo "Chamada perdida do assinante $2, que estava ligando sobre $subject." | mail -s "Chamada perdida de $2" $address
 echo "Chamada perdida para $address do assinante $2, que estava ligando sobre $subject. uid=$1" | mail -s "Chamada perdida de $2" admin@lucky.ru
 ;;
 1)
 echo "Chamada perdida de $2. Fila desconhecida. uid=$1" | mail -s "Chamada perdida de $2" admin@lucky.ru
 ;;
 esac

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

Breve análise do script:
"sleep 7":

Esta é a mesma pausa de tempo que mencionei anteriormente. Temos uma pausa de 7 segundos. Embora eu ache que um segundo é suficiente.

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

A consulta mysql foi separada em uma variável para maior comodidade.

Em seguida, fazemos uma consulta ao MySQL e filtramos a saída recebida. Removemos todas as opções, exceto «ANSWERED», se houver alguma. Se houver várias opções «ANSWERED», deve-se manter apenas uma. No final, a variável «answer» conterá «ANSWERED» ou «».
Se o valor da variável «answer» não for igual a «ANSWERED», isso se trata de uma chamada perdida. Dependendo do número da fila, usaremos o operador case para definir o endereço para o qual o e-mail de notificação deve ser enviado, e o que deve ser escrito nessa mensagem (parte variável da mensagem).

A seguir, considerando o caso em que a fila é definida no Asterisk, mas não é descrita no script. Neste caso, admin@lucky.ru receberá um e-mail informando que a fila não é conhecida pelo script.

Se a fila estiver descrita, um e-mail será enviado para o endereço apropriado e um e-mail duplicado será enviado para admin@lucky.ru com a indicação do «uniqueid», para que seja possível rastrear os eventos dessa chamada, se necessário.

Este script termina aqui.

Vale mencionar que, para a conexão com o MySQL, utilizamos o login e a senha que já conseguimos. No FreePBX, para descobrir o login do usuário Asterisk no MySQL, execute o seguinte comando:

cat /etc/amportal.conf | grep AMPDBUSER

E para descobrir a senha do usuário Asterisk no MySQL, execute o seguinte comando:

cat /etc/amportal.conf | grep AMPDBPASS

Configuração do Asterisk

Estamos usando o FreePBX. No FreePBX, existem diferentes tipos de arquivos de configuração (veja https://asterisk-pbx.ru/wiki/freepbx/files), alguns deles são sobrescritos pelo FreePBX durante a reinicialização, enquanto outros não são sobrescritos (chamam-se custom), pois são especificamente destinados ao usuário.

Trabalharemos com o arquivo de configuração «extensions_override_freepbx.conf», pois ele pertence ao tipo custom.

Primeiro, vamos garantir que o arquivo «/etc/asterisk/extensions.conf» tenha o arquivo «extensions_override_freepbx.conf» conectado. Para isso, execute o seguinte comando:

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

Vamos editar o arquivo «/etc/asterisk/extensions_override_freepbx.conf» e ajustá-lo da seguinte forma:

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,)
#####################

Como mencionei anteriormente, o símbolo «&» no final é obrigatório. Como estaremos trabalhando em um script bash com dados CDR diretamente do banco de dados MySQL, e esses dados são inseridos no MySQL somente após a execução de «exten => h,2,Macro(hangupcall,)», é necessário não esperar a conclusão da execução do script bash, mas passar para a próxima etapa no Asterisk. O próprio script bash deve conter um atraso antes de executar sua parte principal.

Para que as alterações no arquivo de configuração «/etc/asterisk/extensions_override_freepbx.conf» entrem em vigor, é necessário reiniciar o núcleo do Asterisk com o seguinte comando:

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

Isso deve ser feito após a criação do script bash.

Conclusão

Provavelmente, este é o 1001º modo de 'capturar chamadas perdidas' no Asterisk. Compartilhe nos comentários como você resolve essa tarefa. E o que, na sua opinião, pode ser melhorado/reformulado/otimizado. Agradeceremos por ideias construtivas.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster