среда, 27 августа 2008 г.

Fax/SMTP gateway для CallWeaver

Задача: отправить факс путем отправки письма с вложенным ps/pdf/tif, принять факс в виде почтового сообщения с вложением. Инструменты - CallWeaver и какой-то враппер для ОGI и Manager API на Python, который я вовремя не опакетил, таская с собой, а теперь уж и забыл, откуда взял (да, я понимаю, что я неправ, но вот только сейчас руки дошли хотя бы до публикации решения). Архив со скриптами можно взять здесь.

Работает оно следующим образом. От локального отправителя письмо с вложением получает MTA и передает его на stdin скрипту fax-send.py. Скрипт делает из файла tiff и с помощью Originate коммутирует вызываемого внешнего абонента (контекст [call-fax-send], если не дозвонились, вызывается fail-fax.py) и факс(контекст [fax-send], о результате прохождения факса отправителю сообщает check-fax.py). Параметры передаются через Variable.

Упомянутые контексты описаны так:
[call-fax-send]
exten => 0,1,NoOp(Calling ${RECIPIENT} for sending fax)
exten => 0,2,Dial(SIP/${RECIPIENT}@${PEER},25)
exten => 0,3,NoOp(${DIALSTATUS})
exten => 0,4,DeadOGI(fail-fax.py)

[fax-send]
exten => 0,1,NoOp(Sending file ${FILE} as fax from ${SENDER} to ${RECIPIENT}@${PEER} with NOTIFY=${NOTIFY})
exten => 0,2,GotoIf($[${NOTIFY}=Yes]?3:6)
exten => 0,3,Playback(fax)
exten => 0,4,Playback(beep)
exten => 0,5,Wait(2)
exten => 0,6,Set(LOCALSTATIONID=CallWeaver)
exten => 0,7,Set(LOCALHEADERINFO=CallWeaver Fax)
exten => 0,8,TxFAX(${FILE})
exten => h,1,NoOp(RX: REMOTESTATIONID is ${REMOTESTATIONID})
exten => h,2,NoOp(RX: PHASEESTATUS is ${PHASEESTATUS})
exten => h,3,NoOp(RX: PHASEESTRING is ${PHASEESTRING})
exten => h,4,DeadOGI(check-fax.py)
Локальный же получатель факсов переадресует внешнего отправителя в контекст [fax-receive], там получившийся файл подбирает read-fax.py, он же сообщает о неудаче.

Контекст для приема факсов:
[fax-receive]
exten => _0.,1,Set(SENDER=${CALLERID(num)})
exten => _0.,2,Set(RECIPIENT=${EXTEN:1})
exten => _0.,3,Set(LOCALSTATIONID=Vertol EXPO)
exten => _0.,4,Set(LOCALHEADERINFO=Vertol EXPO Fax)
exten => _0.,5,Set(FILE=/data/callweaver/fax-receive/${UNIQUEID}.tif)
exten => _0.,6,RxFAX(${FILE})
exten => h,1,NoOp(RX: REMOTESTATIONID is ${REMOTESTATIONID})
exten => h,2,NoOp(RX: PHASEESTATUS is ${PHASEESTATUS})
exten => h,3,NoOp(RX: PHASEESTRING is ${PHASEESTRING})
exten => h,4,DeadOGI(read-fax.py)
Отлов исключений сделан только там, где без него совсем грустно (например, MTA лучше не знать, что внутри fax-send.py приключилось что-то нехорошее). В OGI невозможность удалить файл, например, ни к чему плохому не приводит.

Да, о поддержке факсов в CallWeaver читать здесь.
Отправить комментарий