✅ Siguiente Paso
Integra este sistema con un dashboard o agrega confirmación de lectura. O continúa con el siguiente módulo práctico del curso.
Convierte el buzón de voz en un sistema proactivo con externnotify, scripts y buenas prácticas de producción
Las notificaciones por email son lentas y a menudo se pierden en bandejas de entrada saturadas. Los usuarios no se enteran de que tienen mensajes de voz importantes hasta que es demasiado tarde. ¿Cómo hacer que una notificación de voicemail sea tan inmediata como un mensaje de texto?
Usaremos la potente función externnotify de Asterisk. Esta directiva ejecuta un script personalizado cada vez que se deja un nuevo mensaje de voz. Nuestro script actuará como puente entre Asterisk y una API web (WhatsApp).
Antes de tocar configuración o scripts, realiza un respaldo y asegura el servidor.
cd /etc/asteriskcp -rfv . ../asterisk.bk-$(date +%F-%H%M)Esto genera una carpeta con timestamp para rollback rápido.
Si no lo configuraste en talleres previos, limita puertos de señalización y media:
ufw allow 5060/udpufw allow 10000:20000/udp# (Opcional) Restringe a tu red/local o IPs de confianzaufw allow from 192.168.1.0/24 to any port 5060 proto udpufw allow from 192.168.1.0/24 to any port 10000:20000 proto udpPrimero, necesitamos un sistema de buzón de voz funcional.
voicemail.conf# Estando en /etc/asterisk/nano voicemail.confLimpia el archivo si tiene contenido de ejemplo y añade la siguiente configuración (usaremos [default]).
[general]format=wav49|gsm|wavserveremail=asterisk@tudominio.comattach=yesmaxsilence=10silencethreshold=128maxlogins=3moveheard=yes
[default]; sintaxis: buzon => contraseña,Nombre Completo,email1001 => 1234,Usuario Oficina,email@dominio.com1002 => 5678,Agente Soporte,email2@dominio.com1003 => 9012,Personal Almacen,email3@dominio.compjsip.confAñadimos mailboxes= en el objeto endpoint para activar MWI (Message Waiting Indicator) y asociación con el buzón.
nano /etc/asterisk/pjsip.conf; --- Extensión 1001: Usuario de Oficina ---[1001](endpoint-template)context=cat1mailboxes=1001@default ; <--- Añadir esta líneaauth=1001aors=1001callerid = Usuario Oficina <1001>
; --- Extensión 1002: Agente Soporte ---[1002](endpoint-template)context=cat2mailboxes=1002@default ; <--- Añadir esta líneaauth=1002aors=1002callerid = Agente Soporte <1002>
; --- Extensión 1003: Teléfono Almacén ---[1003](endpoint-template)context=cat3 ; categoría propia si aplicamailboxes=1003@default ; <--- Añadir esta líneaauth=1003aors=1003callerid = Almacen <1003>Necesitamos dos cosas: una forma de dejar mensajes y una forma de escucharlos.
extensions_anexos.conf para desviar a buzón según DIALSTATUS:nano extensions_anexos.conf[anexos-internos]; Lógica para llamar entre extensiones internas (1001, 1002, 1003)exten => _100X,1,NoOp(Llamada interna a la extension ${EXTEN}) same => n,Set(BUZON=${EXTEN}) ; Guarda el número de extensión en variable BUZON same => n,Dial(PJSIP/${EXTEN},20,tT) same => n,Goto(s-${DIALSTATUS},1) ; Salta a etiqueta según resultado
exten => s-BUSY,1,Voicemail(${BUZON}@default,b) ; Ocupado -> anuncio "busy" same => n,Hangup()
exten => s-NOANSWER,1,Voicemail(${BUZON}@default,u) ; No contesta -> "unavailable" same => n,Hangup()
exten => _s-.,1,Goto(s-NOANSWER,1) ; Otros estados -> unavailable
; [anexos-internos]; ; Lógica para llamar entre extensiones internas (1001, 1002, 1003); exten => _100X,1,NoOp(Llamada interna a la extension ${EXTEN}); same => n,Dial(PJSIP/${EXTEN},30,tT); same => n,Hangup()extensions_funciones.conf:nano extensions_funciones.conf[funciones-voicemail]; El usuario marca *97 y Asterisk usa su CallerID para ir directo a su buzónexten => *97,1,NoOp(Acceso a buzón de voz para ${CALLERID(num)}) same => n,Answer() same => n,VoicemailMain(${CALLERID(num)}@default) same => n,Hangup()
exten => *98,1,NoOp(Acceso a cualquier buzon) same => n,Answer() same => n,VoicemailMain() same => n,Hangup()extensions_categorias.conf:nano extensions_categorias.conf[cat1]include => anexos-internosinclude => funciones-voicemail ; <-- Añadirinclude => salidas-celular
[cat2]include => anexos-internosinclude => funciones-voicemail ; <-- Añadir
[cat3]include => anexos-internosinclude => funciones-voicemailUsaremos CallMeBot, un servicio gratuito que permite enviar mensajes de WhatsApp vía una API HTTP GET.
51987654321).notify_whatsapp.shnano /var/lib/asterisk/agi-bin/notify_whatsapp.sh#!/bin/bash
# --- MODO DE SIMULACIÓN ---# Poner en "true" para escribir en un log en lugar de enviar un mensaje real.# ¡Perfecto para probar sin gastar cuota y si el servicio está caído!SIMULATION_MODE="true"
# --- CONFIGURACIÓN DE LA API (REEMPLAZAR CON TUS DATOS) ---PHONE_NUMBER="TU_NUMERO_DE_TELEFONO" # Ej: 51987654321API_KEY="TU_API_KEY"
# --- CAPTURA DE ARGUMENTOS DE ASTERISK ---# externnotify pasa estos argumentos al script.VM_CONTEXT="$1"VM_MAILBOX="$2"VM_CALLERID_NUM="$3"VM_CALLERID_NAME="$4"VM_DURATION="$5"
# --- LÓGICA DEL SCRIPT ---LOG_FILE="/var/log/asterisk/whatsapp_notifications.log"
# Formateamos el mensaje que queremos enviar# Usamos URL encoding para los espacios (%20) y saltos de línea (%0A)MESSAGE="¡Nuevo%20Voicemail!%0A-%20Buzón:%20${VM_MAILBOX}%0A-%20De:%20${VM_CALLERID_NAME}%20(${VM_CALLERID_NUM})%0A-%20Duración:%20${VM_DURATION}%20segundos."
if [ "$SIMULATION_MODE" = "true" ]; then # MODO SIMULACIÓN: Escribimos en un archivo de log echo "$(date): SIMULACIÓN - Mensaje para ${PHONE_NUMBER}: ${MESSAGE}" >> ${LOG_FILE}else # MODO REAL: Construimos la URL y la llamamos con curl URL="https://api.callmebot.com/whatsapp.php?phone=${PHONE_NUMBER}&text=${MESSAGE}&apikey=${API_KEY}"
echo "$(date): ENVIANDO - Mensaje para ${PHONE_NUMBER}" >> ${LOG_FILE} # Usamos curl para hacer la petición a la API. -s (silencioso), -o /dev/null (descarta la salida) curl -s -o /dev/null "$URL"fi
exit 0chmod +x /var/lib/asterisk/agi-bin/notify_whatsapp.shexternnotifyDile a Asterisk que use el script cada vez que llegue un nuevo voicemail.
nano /etc/asterisk/voicemail.confAñade en [general]:
[general]...externnotify=/var/lib/asterisk/agi-bin/notify_whatsapp.sh...asterisk -rx "voicemail reload"asterisk -rx "dialplan reload"asterisk -rx "pjsip reload"asterisk -rvvvtouch /var/log/asterisk/whatsapp_notifications.log && tail -f /var/log/asterisk/whatsapp_notifications.log1001, llama a la 1002.externnotify se ejecutó.Mon Oct 28 10:30:00 2024: SIMULACIÓN - Mensaje para 51987654321: ¡Nuevo%20Voicemail!...SIMULATION_MODE="false", revisa tu WhatsApp.1002, marca *97 para entrar a tu buzón y escuchar el mensaje. La luz MWI debería encenderse./var/log/asterisk/full y /var/log/asterisk/whatsapp_notifications.log.chmod y propiedad (usuario asterisk).%0A entre líneas.API_KEY y PHONE_NUMBER en variables de entorno o archivo protegido; exporta y usa en el script.curl.✅ Siguiente Paso
Integra este sistema con un dashboard o agrega confirmación de lectura. O continúa con el siguiente módulo práctico del curso.