Faxing with Asterisk

The Good, The Bad, and The Ugly with VoIP Faxing

Nerd Vittles' Faxing with Asterisk allows you to send and retrieve faxes using your PBX in a Flash system. Incoming faxes are converted to PDF format and then forwarded to an email address of your choice. Outbound faxing allows you to transmit a PDF document as a fax to any fax machine in the world.

Faxing with Asterisk 1.8

Update: For those using Asterisk 1.8, see this recent Nerd Vittles article for an even more robust faxing solution.

Prerequisites

Faxing with Asterisk needs a LAMP-based platform (Linux, Apache, MySQL, and PHP) with either the Flite or Cepstral text-to-speech (TTS) engine installed. We recommend PBX in a Flash. To deliver incoming faxes by email, you also will need a functioning email platform on your server. This application has only been tested with Asterisk 1.4 primarily because Asterisk 1.6 still is in beta and some functionality may change before its final release.

How It Works

To receive an inbound fax, simply transfer the incoming fax call to F-A-X (329). The fax will be retrieved with rxfax and delivered to your predefined email address. To send a fax, you first must prepare a PDF document with the material to be faxed. Then name the document using the number to which it is to be delivered via fax. Next place the document (e.g. 6781234567.pdf) in the /tmp folder on your Asterisk server. Finally, pick up a phone on your server and dial F-A-X-I-T (32948). When prompted, enter the phone number to which the fax should be delivered. Hang up when you hear the fast busy disconnect tone.

Installing the Fax Application

This tutorial assumes that you already have installed the fax application on your PBX in a Flash server. For step-by-step instructions, read the Nerd Vittles article.

Dialplan Setup

Most of the heavy-lifting for the faxing application is handled by several additions to the Asterisk dialplan. With PBX in a Flash systems, these additions are automatically made by the installer. The insertions are inserted into the extensions_custom.conf file in /etc/asterisk as part of the install. On other systems, you may need to manually add the following code to the [from-internal-custom] context in extensions_custom.conf:

exten => 329,1,Answer ; F-A-X
exten => 329,n,Wait(1)
exten => 329,n,NVfaxdetect(5)
; You can add an optional destination for non-fax calls to this extensions here
exten => 329,n,Hangup
exten => fax,1,Goto(ext-fax,in_fax,1)

exten => 32948,1,Answer
exten => 32948,n,Wait(1)
exten => 32948,n,Goto(faxit,s,1)

At the end of the extensions_custom.conf file, a number of contexts automatically are added by the installer. If you performed a manual install, you will need to add the following contexts. If you're using Flite instead of Cepstral for text-to-speech on your server, replace the word Swift in the fourth, eighth, and fifteenth lines of the [faxit] context with the word Flite.

[ext-fax]
exten => in_fax,1,StopPlaytones ; you must do this or it will play ring sounds over your fax
exten => in_fax,2,GotoIf($[${FAX_RX} = system]?3:analog_fax,1)
exten => in_fax,3,Macro(faxreceive)
exten => in_fax,4,Hangup
exten => analog_fax,1,GotoIf($[${FAX_RX} = disabled]?3:2) ;if fax is disabled, just hang up
exten => analog_fax,2,DBGet(DIAL=DEVICE/${FAX_RX}/dial);
exten => analog_fax,3,Dial(${DIAL},20,d)
exten => analog_fax,4,Hangup
exten => out_fax,1,txfax(${TXFAX_NAME}|caller)
exten => out_fax,2,Hangup
exten => h,1,system(/var/lib/asterisk/bin/fax-process.pl --to ${EMAILADDR} --from ${FAX_RX_FROM} --subject "Fax from ${URIENCODE(${CALLERID(number)})} ${URIENCODE(${CALLERID(name)})}" --attachment fax_${URIENCODE(${CALLERID(number)})}.pdf --type application/pdf --file ${FAXFILE});
exten => h,2,system(rm ${FAXFILE})
exten => h,3,Hangup()

[sendfax]
exten => s,1,Answer
exten => s,2,Wait(1)
exten => s,3,NoOp(NEWFILENAME: ${NEWFILENAME})
exten => s,4,TxFAX(${NEWFILENAME}|caller)
exten => s,5,Hangup()

[faxit]
exten => s,1,Wait(1)
exten => s,n,Set(TIMEOUT(digit)=7)
exten => s,n,Set(TIMEOUT(response)=10)
exten => s,n,Swift("Place the PDF document with a matching destination phone number in the server's TEMP directory. To proceed: please enter the fax destination phone number now: ")
exten => s,n,Background(beep)
exten => s,n,Read(NUM2CALL,beep,10)
exten => s,n,GotoIf($["foo${NUM2CALL}" = "foo"]?2,1)
exten => s,n,Swift("Your fax will be sent to the following number:")
exten => s,n,SayDigits(${NUM2CALL})
exten => s,n,Background(custom/nv-press8)
exten => s,n,WaitExten(10)
exten => s,n,Goto(2,1)
exten => i,1,Goto(2,1)
exten => o,1,Goto(2,1)
exten => 2,1,Swift("Your fax request has been cancelled.")
exten => 2,2,Background(goodbye)
exten => 2,3,Hangup()
exten => 8,1,Set(CID=${CALLERID(num)})
exten => 8,n,Set(INFILE=/tmp/${NUM2CALL}.pdf)
exten => 8,n,Set(OUTFILE=/tmp/${NUM2CALL}.tif)
exten => 8,n,System(gs -q -dNOPAUSE -dBATCH -dSAFER -sDEVICE=tiffg3 -sOutputFile=${OUTFILE} -f ${INFILE})
exten => 8,n,System(echo Channel: local/${NUM2CALL}@from-internal > /tmp/${CID})
exten => 8,n,System(echo SetVar: LOCALHEADERINFO=PBX in a Flash >> /tmp/${CID})
exten => 8,n,System(echo SetVar: LOCALSTATIONID=678-555-1212 >> /tmp/${CID})
exten => 8,n,System(echo SetVar: FAXRECEIVER=${NUM2CALL} >> /tmp/${CID})
exten => 8,n,System(echo SetVar: NEWFILENAME=${OUTFILE} >> /tmp/${CID})
exten => 8,n,System(echo Context: sendfax >> /tmp/${CID})
exten => 8,n,System(echo Extension: s >> /tmp/${CID})
exten => 8,n,System(echo Priority: 1 >> /tmp/${CID})
exten => 8,n,System(echo Callerid: ${CID} >> /tmp/${CID})
exten => 8,n,System(echo MaxRetries: 0 >> /tmp/${CID})
exten => 8,n,System(echo WaitTime: 50 >> /tmp/${CID})
exten => 8,n,System(chmod 775 /tmp/${CID})
exten => 8,n,System(echo sleep 10 > /tmp/${CID}.2)
exten => 8,n,System(echo mv /tmp/${CID} /var/spool/asterisk/outgoing >> /tmp/${CID}.2)
exten => 8,n,System(chmod 775 /tmp/${CID}.2)
exten => 8,n,Background(thank-you-for-calling)
exten => 8,n,Background(goodbye)
exten => 8,n,Hangup()
exten => h,1,System(/tmp/${CID}.2)

NOTE: Even with the automatic install, make sure you change your outbound fax number in the exten => 8 section above by replacing 678-555-1212 with your actual number.

Setting Default Email Delivery Address

Log into your server as root and edit /var/lib/asterisk/bin/fax-process.pl. Change the following default parameter to make it your default MAILTO email address: my $to = "JoeSchmoe\@gmail.com";

FreePBX Setup

Connect to your PBX in a Flash server with FreePBX in your browser, and click on the Setup tab and then Misc Destinations. Add new entries for Fax with 329 as the Dial entry. And add a second Misc Destination for FaxIt with 32948 as the Dial entry. Here's how each entry should look:

 Add Misc Destination
description:
dial:   

 Add Misc Destination
description:
dial:   

Next, click on the Setup tab again and choose General Settings. Scroll down to the Fax Machine section and fill in the blanks using the following example as a model.

 Fax Machine
Extension for Receiving Faxes:
Email Faxes To:
Faxes Emailed From:

Make sure the From Address for your emails matches the FQDN that you entered in /etc/hosts. Then Save your entries and reload your Asterisk dialplan when prompted to do so.

Configuring an Inbound Route for Faxes

If you plan to receive faxes from outside of your Asterisk server, then you'll need to configure a DID and InBound Route in FreePBX to accept the fax calls. The easiest way to accomplish this is to create a custom configuration in /etc/asterisk/extensions_custom.conf to process the incoming calls. This is especially important if this DID number will also be used to accept standard telephone calls. Be aware that SIP providers are notoriously bad at providing SIP trunks of acceptable quality and with corrrect settings to handle incoming faxes. Of about a dozen providers, the only four that have provided reliable incoming fax support in our users' testing are TelaSIP, Teliax, voip.ms, and Future-Nine. With Teliax and Future-Nine, you will need to add the following settings to your Incoming Trunk Configuration in FreePBX:

t38pt_rtp=no
t38pt_tcp=no
t38pt_udptl=no

You may have better luck with standard telephone trunks from MaBell in conjunction with an FXO port on your server or ATA.

While still in FreePBX, click on the Setup tab again and choose Inbound Routes. Then click on the Trunk you plan to use to receive the incoming faxes. Scroll down to the Set Destination section of the form, and make a Custom App entry that looks like the following:

 Route: Telasip
Custom App:

Then add a new custom-telasip-in context at the end of /etc/asterisk/extensions_custom.conf that looks something like the following and then reload your dialplan: asterisk -rx "dialplan reload"

[custom-telasip-in]
exten => s,1,Answer
exten => s,2,Wait(1)
exten => s,3,NoOp(Incoming call on TelaSIP #6781234567)
exten => s,4,Playtones(ring)
exten => s,5,NVfaxdetect(5)
exten => s,6,Goto(app-daynight,1,1)
exten => s,7,Hangup
exten => fax,1,Goto(ext-fax,in_fax,1)

When an incoming call is received on this trunk, Asterisk will play a ring tone to the caller while listening for a fax tone for 5 seconds. If the fax tone is detected, the call will be transferred to the ext-fax context for processing. Otherwise, the incoming call will be sent to the Day/Night Feature Code 1 context in FreePBX.

Test Drive Incoming Faxes to Asterisk

You can try out inbound faxing by placing a fax machine on an extension on your PBX using an FXS device such as the SP-1001. Place a document in the fax machine and dial F-A-X. The newly created fax extension should answer the call, receive the fax, and email it to the destination address you specified above. Then you're ready to test receipt of a fax from an outside number by placing a call to the DID you designated above to receive faxes.

Nerd Vittles Original Article (11/14/2008): The Lean, Mean Asterisk Machine: And Now It's a Fax Machine, Too!