Помимо двух настоящих извращений - хоккея на траве и балета на льду,существует и третье - диалап через ip-телефонию. (народная мудрость)
Задача
- Организовать автоматизированный шлюз для пересылки документов полученных через электронную почту, адресатам на типовые факсовые аппараты подключенные в телефонную сеть.
- Обеспечить статистику и контроль доставки с ведением базы данных по событиям
Требования к системе
- Наличие доступа по протоколу POP3 к выделенному для этой цели почтовому ящику. Ящик не должен использоваться для других целей, все письма попадающие в него будут удаляться.
- Наличие доступа к телефонной сети посредством VoIP (IAX2,SIP) с поддержкой aLaw или uLaw или иных средств доступных для использования совместно с Asterisk.
Условия в примере
Реальный или виртуальный сервер на базе ОС Ubuntu Server 12.04 имеющий сетевой доступ к учетным записям:
- IAX2 (VoIP Asterisk пользователь: user пароль: 123 адрес: 11.22.33.44)
- POP3 (пользователь: user пароль: 123 адрес: mail.local)
Письма автоматически формируются платформой 1Сv82 по принципу:
- Адрес получателя - efax@mail.local
- Тема и содержимое не важно
- Только одно почтовое вложение в формате pdf (средствами платформы 1с)
Имя вложения содержит всю необходимую информацию, например:
- msk_0004567_84991112233-1_9-18_1-5.pdf где:
- "_" - знак разделения значащих полей
- msk - префикс базы 1с (филиала)
- 0004567 - номер документа
- 84991112233 - номер абонента (получателя факса). 1 - добавочный номер, если указан то до набрать в тоновом режиме (например прямой номер факса автомата)
- 9-18 - время доступности факса у абонента с 9 до 18 часов
- 1-5 - дни недели, когда доступен прием факса у абонента (с пн по пт)
Принцип работы
Логический
- Выполняется периодическая проверка почтового ящика и в случае обнаружения в нем писем они скачиваются системой
- Генерируется случайный уникальный код, который будет участвовать во всех этапах движения этого документа и попадет в статистику
- Из скачиваемых писем извлекаются вложения и складываются в папку входящих
- Из этой папки выбирается файл отвечающий требованиям к формату имени
- Из имени файла выделяются значащая информация и сохраняется в базу данных
- Файл отправляется на доставку факсовому серверу, сам файл перемещается в папку обработка
- Факсовый сервер на основании переданных параметров помещает факс в очередь на отправку
- Через виртуальный модем подключенный к серверу ИП телефонии производится дозвон до получателя
- С помощью синтеза голоса получатель уведомляется о сути звонка
- С помощью распознавания голоса в базу данных заносится информация от получателя (напр. ФИО, должность)
- По результату звонка в базу заносится информация об успешности или не успешности отправки факса с указанием причины
- На том-же основании файл перемещается в соответствующую папку
По компонентам
- MySQL сервер для хранения статистики
- Fetchmail забирает письма с внешнего почтового ящика по протоколу pop3 и передает их Procmail
- Procmail (обработчик почтовых сообщений) передает тело письма программе ripmime, а затем запускает bash-скрипт обработки
- uudeview извлекает из письма прикрепленный файл и сохраняет в папку входящих
- bash-скрипт анализирует формат названия файла, передает файл в Hylafax, пишет в mysql полученную информацию
- Hylafax (факс сервер) получив задание выполняет дозвон через iaxmodem, получателю факса
- iaxmodem подключен к локальному серверу Asterisk (можно создать множество модемов)
- Asterisk выполняет подключение к городской телефонной сети через voip протокол, обеспечивает голосовое приветствие
- API Google используется для синтеза и распознавания голоса в момент ответа абонента, через ARI скрипты Asterisk
Подготовительные работы
Установка компонентов
apt-get update apt-get install lamp-server^ asterisk iaxmodem hylafax-server postfix procmail fetchmail uudeview
Мастера установки спросят пароль для сервера mysql (запомним его), libvpb0 оставим по умолчанию 7, а для Postfix Configuration выберем Без настройки
Создание базы данных
Вся статистика работы факс-шлюза будет хранится в базе на mysql сервере.
- Создадим новую базу faxstats
- Войдем в консоль mysql и выполним запрос на создание базы и таблицы, а так-же назначим права доступа:
mysql -p
Скопируем и вставим
# Создаем базу faxstats
CREATE DATABASE faxstats
CHARACTER SET utf8
COLLATE utf8_general_ci;
# Тут назначим права и разрешим удаленное подключение к базе
# Пользователь faxstats
# Пароль isolda
grant usage on *.* to faxstats@localhost identified by 'isolda';
grant all privileges on faxstats.* to faxstats@localhost;
# Создаем таблицу mailtofax для событий получения файлов
USE faxstats;
CREATE TABLE
mailtofax
(
uniqid TEXT(10),
eventdate DATETIME,
preffil TEXT(8),
id TEXT(64),
numbertel TEXT(64),
namefile TEXT(64),
jobnumber INTEGER
);
# Создадим таблицу asterstats для сохранения результатов распознавания голоса.
CREATE TABLE
asterstats
(
uniqid TEXT(10),
eventdate DATETIME,
numbertel TEXT(64),
namesotr TEXT(254)
);
# Создадим таблицу xferfaxlog для переноса в нее лога hylafax
CREATE TABLE
xferfaxlog
(
eventdate DATETIME,
ENTRYTYPE TEXT(32),
COMMID TEXT(32),
MODEM TEXT(32),
JOBID TEXT(8),
JOBTAG TEXT(32),
USERID TEXT(32),
LOCALNUMBER TEXT(32),
TSI TEXT(32),
PARAMS TEXT(32),
NPAGES TEXT(8),
JOBTIME TIME,
CONNTIME TIME,
REASON TEXT(254),
CIDNAME TEXT(128),
CIDNUMBER TEXT(128),
CALLID TEXT(128),
OWNER TEXT(32),
DCS TEXT(254),
JOBINFO TEXT(254)
);
exit
Почтовая часть
На данном этапе мы решаем задачу по подключению к почтовому, скачивание из него писем, извлечение из них вложений и запуска обработчика этих вложений
Пути и папки
- Создадим папки для сохранения вложений
mkdir /home/efax/ && cd /home/efax/ mkdir IN PROC ERR OK
fetchmail получение почты
Сохраняем копию оригинального файл конфигурации, очищаем его и пишем свои параметры
cp /etc/fetchmailrc /etc/fetchmailrc.orig echo ""> /etc/fetchmailrc nano /etc/fetchmailrc
Внесем свои параметры
set daemon 10 # Проверка новых писем (в сек) # Параметры подключения к почтовому ящику poll mail.local # Адрес сервера proto pop3 # Протокол получения писем user user # Логин pass 123 # Пароль sslproto "" # Не ругаться на сертификат mda 'procmail -d %T' # Передача управления procmail
Разрешаем запуск демона (службы)
echo "START_DAEMON=yes" > /etc/default/fetchmail /etc/init.d/fetchmail restart
procmail обработка писем
Задача принять от fetchmail письмо и направить его в uudeview для извлечения вложений и сохранения их в папку входящих, а затем передать управление bash-скрипту.
nano /etc/procmailrc
Внесем параметры:
:0 * ^From:.* { :0 f | uudeview -iq - -p /home/efax/IN/ :0 | /home/efax/mailtofax }
Обработка вложений
Для выбора и обработки вложений создадим скрипт:
nano /home/efax/mailtofax
# Путь до папки с входящими
pathin=/home/efax/IN
# Путь до папки с обрабатываемыми документами
pathproc=/home/efax/PROC
# Шаблон (регулярное выражение) для выборки файлов
freg=".+_.+_.+\.pdf"
# Параметры базы mysql
dbuser=faxstats
dbpass=isolda
dbname=faxstats
dbtable=mailtofax
# Составляем список всех файлов соответствующих шаблону
lsfiles=`ls -tr /home/efax/IN| grep -P $freg`
for namefile in $lsfiles; do
IFS="_"
set -- $namefile
# Разбираем имя файла на переменные
preffil=$1
id=$2
numbertel=`echo $3|awk -F "-" '{print $1}'`
numberdtmf=`echo $3|awk -F "-" '{print $2}'`
worktime=$4
workdays=$5
Сохраняем время и дату
eventdate=`date +"%Y/%m/%d %T"
`
# Перемещаем файл в обработку
mv "$pathin/$namefile" "$pathproc/$namefile"
# Генерим уникальный 10 значный ключ файла
uniqid=`head -c 10 /dev/urandom|cksum|awk '{print $1$1}'|head -c 10`
# Отправляем файл на доставку
istr=`sendfax -n -d "$numbertel*$uniqid*$numberdtmf" "$pathproc/$namefile"`
jobnumber=`echo $istr|grep -Po "request id is \d+"|awk '{print $4}'`
echo "$uniqid;$eventdate;$preffil;$id;$numbertel;$namefile;$jobnumber" >> /var/log/mailfax.log
# Добавляем запись в базу
mysql -u$dbuser -p$dbpass -D $dbname -e "INSERT INTO $dbtable \
( uniqid, eventdate, preffil, id, numbertel, namefile, jobnumber) values \
('$uniqid','$eventdate','$preffil','$id','$numbertel','$namefile','$jobnumber');"
done
Делаем скрипт исполняемым
chmod +x /home/efax/mailtofax
Телефония
Локальный Asterisk сервер нужен для того, чтобы:
- Обеспечить виртуальным модемам постоянное подключение
- Управлять голосовыми приветствиями и логикой взаимодействия с получателем факса.
- Обеспечить маршрутизацию вызовов через один или несколько внешних транков
Настройка каналов
Создадим учетную запись IAX2 на нашем (локальном) asterisk сервере, для регистрации iaxmodem, а так-же транк для подключения к провайдеру IP телефонии (например тоже через IAX2 протокол) для совершения исходящих вызовов.
- iaxmodem будет регистрироваться на номере 910 с паролем faxfax123
- Во внешний мир наш сервер будет выходить через IAX2 транк с параметрами:
- адрес сервера 11.22.33.44
- имя пользователя user
- пароль 123
копируем оригинальный файл, очищаем оригинальный файл и создаем свой
cp /etc/asterisk/iax.conf /etc/asterisk/iax.conf.orig echo "" > /etc/asterisk/iax.conf nano /etc/asterisk/iax.conf
Вносим свои параметры:
[general] disallow=all allow=alaw # Для подключения модема серверу [910] host=dynamic type=friend secret=faxfax123 requirecalltoken=no context=from-iaxmodem # Для подключения сервера к внешнему миру [iaxprovider] type=peer host=11.22.33.44 username=user fromuser=user secret=123 qualify=yes
Настройка плана набора
- Для создания интерактивного меню с синтезом и распознаванием голоса для взаимодействия с абонентом, подключим Asterisk к API функциям работы с голосом от комании Google
Синтез и распознавание голоса в Asterisk
- Создаем план набора (dialplan)
cp /etc/asterisk/extensions.conf /etc/asterisk/extensions.conf.orig echo "" > /etc/asterisk/extensions.conf nano /etc/asterisk/extensions.conf
Вносим свои параметры:
[from-iaxmodem]
# Выделяем из набора номер телефона, уникальный код и добавочный номер
exten => _X.,1,Set(dialnum=${CUT(EXTEN,"*",1)})
exten => _X.,n,Set(uniqid=${CUT(EXTEN,"*",2)})
exten => _X.,n,Set(dtmfnum=${CUT(EXTEN,"*",3)})
# Если в номере стоит добавочный то набрать его в тоновом режиме
exten => _X.,n,GotoIf($["${dtmfnum}" = ""]?itr)
exten => _X.,n,Dial(iax2/khb-jde27/${dialnum},,M(dtmfdial^${dtmfnum}))
# Звонок с интерактивным меню
exten => _X.,n(itr),Dial(iax2/khb-jde27/${dialnum},,M(priv^${dialnum}^${uniqid}^${dtmfnum}))
[macro-dtmfdial]
exten => _.,1,Answer
exten => _.,n,Wait(1)
exten => _.,n,SendDTMF(w${ARG1})
[macro-priv]
exten => _.,1,Answer
exten => _.,n,Wait(1)
exten => _.,n,AGI(say.php,"Здравствуйте‚!")
exten => _.,n,AGI(say.php,"скажите имя сотрудника!") #Запись услышанного
exten => _.,n,Record(/tmp/${UNIQUEID}.wav,3,20) #Запись услышанного
exten => _.,n,AGI(say.php,"вы сказали")
exten => _.,n,Playback(/tmp/${UNIQUEID})
exten => _.,n,AGI(voice.php,/tmp/${UNIQUEID})
exten => _.,n,AGI(say.php,"я услышала")
exten => _.,n,AGI(say.php,"${VOICE}")
exten => _.,n,System(/home/efax/asttosql "${VOICE}" ${ARG1} ${ARG2} ${ARG3})
Перезапускаем Asterisk
/etc/init.d/asterisk restart
Добавляем скрипт на добавление результата распознавания голоса в базу
nano /home/efax/asttosql
# Параметры базы mysql
dbuser=faxstats
dbpass=isolda
dbname=faxstats
dbtable=asterstats
eventdate=`date +"%Y/%m/%d %T"`
namesotr=$1
numbertel=$2
uniqid=$3
# Добавляем запись в базу
mysql -u$dbuser -p$dbpass -D $dbname -e "INSERT INTO $dbtable \
( uniqid, eventdate, numbertel, namesotr) values \
('$uniqid','$eventdate','$numbertel','$namesotr');"
Делаем скрипт исполняемым
chmod +x /home/efax/asttosql
Факсовая часть
Настройка IAXMODEM
Создаем конфигурацию виртуального модема
nano /etc/iaxmodem/iaxmodem-cfg.ttyIAX1
device /dev/ttyIAX1 owner uucp:uucp mode 660 port 4570 refresh 300 server 127.0.0.1 peername 910 secret faxfax123 codec alaw
Запускаем виртуальный модем
/etc/init.d/iaxmodem start
Проверяем лог запуска
cat /var/log/iaxmodem/iaxmodem
Настройка hylafax Server
Запускаем мастер настройки
faxsetup
Отвечаем на все вопросы по умолчанию пока не появится вопрос:
Serial port that modem is connected to [ttyS0]?
Пишем имя порта ttyIAX1
Local identification string (for TSI/CIG) ["NothingSetup"]?
указываем название организации JDE и продолжаем отвечать на вопросы мастера, пока не появится запрос о добавлении второго модема Do you want to run faxaddmodem to configure another modem [yes]? . На него отвечаем No Перезапускаем hylafax
/etc/init.d/hylafax restart
Для управления сервером и контроля состояния можно использовать некоторые полезные команды: |
Посмотреть очередь
faxstat -s
Удалить из очереди задание с номером
faxrm номер
Быстро очистить всю очередь с полными правами
faxrm -a `faxstat -s | grep -Po "^\d+"|tr "\n" " "`
Статистика по факсам
- Скрипт переноса лога hylafax в базу
nano /home/efax/mysqlhyla
#!/bin/bash
########### Параметры #############
# Путь до файла с логом
pathin=/var/spool/hylafax/log/xferfaxlog
# Параметры базы mysql
dbuser=faxstats
dbpass=isolda
dbname=faxstats
dbtable=xferfaxlog
# Переименовываем файл лога для исключения повторного считывания
rans=$RANDOM
mv $pathin $pathin-$rans
# Читаем лог и назначаем переменным значения полей разеденных табом
cat $pathin-$rans| while read line; do
IFS=`printf "\t"`
set -- $line
eventdate=`date -d$1 "+%Y-%m-%d %T"`; shift
ENTRYTYPE="$1"; shift
COMMID="$1"; shift
MODEM="$1"; shift
JOBID="$1"; shift
JOBTAG="$1"; shift
USERID="$1"; shift
LOCALNUMBER="$1"; shift
TSI="$1"; shift
PARAMS="$1"; shift
NPAGES="$1"; shift
JOBTIME="$1"; shift
CONNTIME="$1"; shift
REASON="$1"; shift
CIDNAME="$1"; shift
CIDNUMBER="$1"; shift
CALLID="$1"; shift
OWNER="$1"; shift
DCS="$1"; shift
JOBINFO="$1"; shift
mysql -u$dbuser -p$dbpass -D $dbname -e "INSERT INTO $dbtable \
( eventdate, ENTRYTYPE, COMMID, MODEM, JOBID, JOBTAG, USERID, LOCALNUMBER, TSI, PARAMS, NPAGES, JOBTIME, CONNTIME, REASON, CIDNAME, CIDNUMBER, CALLID, OWNER, DCS, JOBINFO) values \
('$eventdate','$ENTRYTYPE','$COMMID','$MODEM','$JOBID','$JOBTAG','$USERID','$LOCALNUMBER','$TSI','$PARAMS','$NPAGES','$JOBTIME','$CONNTIME','$REASON','$CIDNAME','$CIDNUMBER','$CALLID','$OWNER','$DCS','$JOBINFO');"
done
сделаем его исполняемым
chmod +x /home/efax/mysqlhyla