Asterisk Faxing Part 2: Sending Faxes

Published on Sep 1, 2021
Topics: Asterisk, Coding, VOIP

Turns out that sending fax is a heck of a lot harder than receiving them. Fax machines all have slightly different quirks around how long before they pick up and what they expect to happen. We ended up punting on the problem and signing up for an account with Faxage.

Building an application that could send PDFs and other documents to their API was straight forward and 100% worth the $8 per month or whatever it costs.

Using PHP and Guzzle you can send base 64 encoded file information in a post request to their API. The core logic around sending to the Faxage service is detailed below. Using Laravel or another framework, creating the form, storing the files and all that should be straight forward enough.

<?php

$files = [ __DIR__ . '/files/file1.pdf' ];
$fileNames = [];
$fileData = [];

foreach($files as $index => $filePath) {
    $fileNames[] = "file{$index}.pdf"; // file1.pdf, file2.pdf, etc.    
    $fileData[] = base64_encode(file_get_contents($filePath));
}

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', "https://api.faxage.com/httpsfax.php", [
    'form_params' => [
        'username' => urlencode('faxageusername'),
        'password' => urlencode('faxagepassword'),
        'company' => urlencode('faxage company id'),
        'faxno' => '5551235678', // who we send to
        'callerid' => '5551235679', // our caller ID
        'operation' => 'sendfax',
        'tagname' => 'My Name', // 'sender name' // (eg shows next to 'from' in header) - optional
        'tagnumber' => '5551235679', // number we sent from - shown in header
        'faxfilenames' => $filenames,
        'faxfiledata' => $filedata,
    ],
]);

// When it sends correctly we'll get back a JOB ID 
$contents = $response->getBody()->getContents();
$pieces = explode(':', $contents);

if($pieces[0] === 'JOBID') {
    return (int) $pieces[1];
}

// if you don't get a JOB ID something probably went wrong

You'll store the job ID somewhere, and then check in every so often to get the status and if it sent...

<?php

const JOB_ID_INDEX = 0;
const RESULT_INDEX = 4;
const RESULT_MESSAGE = 5;

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', "https://api.faxage.com/httpsfax.php", [
    'form_params' => [
        'username' => urlencode('faxageusername'),
        'password' => urlencode('faxagepassword'),
        'company' => urlencode('faxage company id'),
        'jobids' => [1,2,3], // pass one or more job ids that you stored when sending
        'operation' => 'status',
    ],
]);

$contents = $response->getBody()->getContents();

$results = [];

// Results come back with each job id one one line, and data is tab delimited
foreach(explode("\n", $contents) as $record) {
    if(empty($record)) {
        continue;
    }

    $data = explode("\t", $record);
    
    $jobId = $data[JOB_ID_INDEX];
    $result = $data[RESULT_INDEX]; // pending, success or failure
    $resultText = $data[RESULT_MESSAGE]; // longer info like Tries: 5, Status: Pending, Retires Left: 3

    // store the result information, or do whatever has to be done
}