The FaxSender property

class CallFaxSender

A class that provides an API for transmitting a fax on a connected call.

This class exposes a public property called Details of type FaxDetails (see below) which provides details on the fax job in progress.

The call channel object uses this class to provide fax transmit functionality. The CallChannel object has a public property called FaxSender of this type. Please see the tutorial for examples on how to use this class.

class Cause

Once a fax transmit job has ended and the transmit State has returned to IDLE or ERROR, the Cause will be one of these.

Fax transmit termination causes are:

ERROR

Transmit has stopped due to an error.

NORMAL

Transmit has stopped normally.

ABORTED

Transmit has been aborted (probably because stop was called).

HANGUP

Transmit ended because the receiver hung up.

TIMEOUT

Transmit stopped because a timer has expired.

NOTFAX

The receiving end has not sent any fax signals, it is probably not a fax machine.

UNKNOWN_OPTION

An unknown fax option was supplied.

UNKNOWN_VALUE

A known fax option value was supplied with an incorrect value.

INCONSISTENT_OPTIONS

Inconsistent fax options were supplied.

STANDARDMISMATCH

A T.30 - T.38 negotiation mismatch has occurred and the call has been abandoned.

COMMSFAULT

A fax communication error has occurred. This could be due to the receiving end not being a fax machine or due to bad line conditions. Check that the receiving end is a compatible fax machine and then try again.

PAGEQUALITY

The Fax has been abandoned because there have been too many errors. Try again.

NONE

Transmit is in progress or transmit has not occurred.

When passing fax options to the send or start functions, the user will supply a dictionary of name - value pairs. These names, and their corresponding values can be found in the online fax documentation. If an invalid variable name or value is supplied, or if an invalid combination of variables is supplied, the action will fail and the cause will be one of UNKNOWN_OPTION, UNKNOWN_VALUE or INCONSISTENT_OPTIONS. It is a good idea to check for these causes as one of them would normally require a correction to the application. An example is given below.

This combination would make faxing impossible:

fax_options = {
    'v17':'NO',
    'MinDataRate':'14400'
}

if channel.FaxSender.start(fax_to_send=fax_to_send, fax_options=fax_options) is False:
    cause = channel.FaxSender.cause()
    if cause == channel.FaxSender.Cause.INCONSISTENT_OPTIONS:
        raise Error("This combination of options is not allowed: {0}".format(repr(channel.FaxSender.Details.failed_option)))

Sometimes a fax session will fail because the other end is not a fax machine (for example, an outbound fax call is answered by a human); In this case the cause will be NOTFAX, for example:

cause = channel.FaxSender.wait_until_finished()
if cause == channel.FaxSender.Cause.NOTFAX:
    raise Hangup("Hang up because other end is not a fax machine")

A fax session can also fail because the line quality is simply too bad for a fax to succeed. For these cases we have the causes COMMSFAULT and PAGEQUALITY. If a fax session fails and the cause is COMMSFAULT, it would be worthwhile checking the line before trying again. If the cause is PAGEQUALITY, it may be worth waiting ten minutes or so and before trying again.

class State

The fax transmit state can be checked to determine whether a fax is in progress. When a fax job ends and State has returned to IDLE or ERROR, the termination Cause can be checked to find the reason why.

Fax transmit states are:

SENDING

A transmit job is in progress.

IDLE

No transmit job is in progress.

ERROR

The most recent transmit job failed and none is currently in progress.

cause()

This function will return a cause.

When a particular job terminates, the reason why can be requested by calling this function.

If this function is called while a job is still running, the cause will be NONE.

send(fax_to_send, fax_options=None)

Send a fax on the current connected call channel.

Required argument:
  • fax_to_send

    the fax document object to send.

Optional arguments:
  • fax_options

    fax configuration options for this session.

fax_to_send is an object that is used to configure the fax document for sending. A reference to the object is passed into this function. If you are not familiar with the fax document object, please read up on it before continuing.

fax_options is a dictionary of name - value pairs where the name is that of a fax option and the value is what that option should be set to. Fax options would normally be set on your inbound and outbound service pages. It is, however, possible to set options from within an application. For instance, to force a high resolution fax:

cause = channel.FaxSender.send(my_fax, fax_options={'HighRes':'YES'})

The list of option names, and their possible values, can be found on the online fax documentation page.

If the call state is IDLE, this function will raise a Hangup exception. If the call state is not IDLE but also not ANSWERED, this function will raise an Error exception.

If the send state is already SENDING, this function will raise an Error exception. If the call channel already has an external audio source, e.g, it is connected to another call channel, this function will raise an Error exception.

This function will block until the fax has been sent or a timeout has expired.

Upon return, this function will return a cause.

Usage example:

my_fax = FaxToSend()
my_fax.set_content('my_outbound_fax.tif')
cause = channel.FaxSender.send(my_fax)
if cause == channel.FaxSender.Cause.NORMAL:
    print("the fax job ended normally")
elif cause == channel.FaxSender.Cause.NOTFAX:
    print("the receiver was not a fax machine")
else:
    print("the fax job failed")
start(fax_to_send, fax_options=None)

Start sending a fax on the current connected call channel.

Required argument:
  • fax_to_send

    the fax document object to send.

Optional arguments:
  • fax_options

    fax configuration options for this session.

fax_to_send is an object that is used to configure the fax document for sending. A reference to the object is passed into this function. If you are not familiar with the fax document object, please read up on it before continuing.

fax_options is a dictionary of name - value pairs where the name is that of a fax option and the value is what that option should be set to. Fax options would normally be set on your inbound and outbound service pages. It is, however, possible to set options from within an application. For instance, to force a high resolution fax:

cause = channel.FaxSender.start(my_fax, fax_options={'HighRes':'YES'})

The list of option names, and their possible values, can be found on the online fax documentation page.

If the call state is IDLE, this function will raise a Hangup exception. If the call state is not IDLE but also not ANSWERED, this function will raise an Error exception.

If the send state is already SENDING, this function will raise an Error exception. If the call channel already has an external audio source, e.g, it is connected to another call channel, this function will raise an Error exception.

This function will block until fax transmission has begun or a timeout has expired.

Upon return, this method will return True for success, otherwise False.

Usage example:

my_fax = FaxToSend()
my_fax.set_content('my_outbound_fax.tif')
# Start sending a fax.
if channel.FaxSender.start(my_fax) == True:
    # while the fax is being sent, we can do something else;
    # and then wait for it to finish.
    cause = channel.FaxSender.wait_until_finished()
    if cause == channel.FaxSender.Cause.NORMAL:
        print("the fax job ended normally")
    elif cause == channel.FaxSender.Cause.NOTFAX:
        print("the receiver was not a fax machine")
    else:
        print("the fax job failed")
else:
    # The function returned False, this probably means that
    # the acknowledgement to indicate that fax sending has begun
    # did not arrive in time, and the function has timed out.
    pass
state()

This function will return the current state.

When a particular job is busy, its state can be tracked by calling this function.

If this function is called while when no job is in progress, the state will be IDLE.

stop()

Stop sending the fax. The current fax session will be aborted.

If the call state is IDLE, this function will raise a Hangup exception. If the call state is not IDLE but also not ANSWERED, this function will raise an Error exception.

If the send state is not SENDING, this function will simply return True. Otherwise, this call will block until fax sending has stopped or a timeout has expired.

Upon return, this method will return True for success, otherwise False.

Usage example:

# Start sending a fax and then stop it.
if channel.FaxSender.start(filename="my_fax.tif") == True:
    # while the file is transmitting we can do something else,
    # ...
    # then, for whatever reason, stop it.
    channel.FaxSender.stop()
wait_for_negotiated_settings(seconds_timeout=None)

Wait for the fax endpoint negotiation to be completed.

Optional argument:
  • seconds_timeout

    The maximum time, in seconds, to wait.

This function will wait until the negotiated settings are available.

If the channel associated with this fax session goes to IDLE, this function will raise a Hangup exception,

If the fax session encounters an error, this function will raise an Error exception.

Once the negotiated settings are available, this function will return the settings dictionary. If the negotiated settings dictionary is empty, this means that fax negotiation has failed.

Usage example:

negotiated_settings = channel.FaxSender.wait_for_negotiated_settings()
if negotiated_settings == {}:
    # negotiation has failed, we should quit and hang up.
    cause = channel.FaxSender.cause()
    raise Hangup("fax receiver returned {0}".format(cause))

for setting, value in negotiated_settings.iteritems():
    print("{0:>15.15} : {1}".format(setting, value))
wait_for_next_page(seconds_timeout=None)

Wait for the next fax page to be completed.

Optional argument:
  • seconds_timeout

    The maximum time, in seconds, to wait.

This function will wait for the next page to be completed.

If the channel associated with this fax session is IDLE, this function will raise a Hangup exception.

If the fax session encounters an error, this function will raise an Error exception.

Once the next page has completed, this function will return the number of pages completed so far.

Usage example:

# We can wait for each page to be sent, we do this until we've been told
# that no more pages will be sent. It is important to note that the last_page
# flag does not indicate success, it simply means that no more pages will be processed.
while channel.FaxSender.Details.last_page is not True:
    pages = channel.FaxSender.wait_for_next_page()
    print("Sent {0} pages so far".format(pages))

# Now we need to wait until the fax session has finished. We need to do this even though
# the last page flag has been set. Remember to check the cause, the last_page indicator
# may have been set, but this does not mean that every page was sent.
cause = channel.FaxSender.wait_until_finished()
if cause != channel.FaxSender.Cause.NORMAL:
    raise Error("The fax sender failed with cause {0}".format(cause))
wait_until_finished(seconds_timeout=None)

Wait for the fax session to complete.

Optional argument:
  • seconds_timeout

    the amount of time allocated to wait for the fax session to complete. Default is to wait forever.

This function will block until the current fax session has finished or the timeout has expired. Giving a value of None for seconds_timeout will enable an infinite wait. If the timeout does expire, this function will return a cause of TIMEOUT.

Upon return, this function will return a cause.

This function will not raise a HANGUP exception if the call state is already IDLE. It is possible for there to be a brief period during which the call can be IDLE whilst the fax session is still terminating.

Usage example:

# Start sending a fax and then wait for it to finish.
if channel.FaxSender.start(filename="my_fax.tif") == True:
    # do something else for a bit
    cause = channel.FaxSender.wait_until_finished()
    if cause == channel.FaxSender.Cause.NORMAL:
        print("the fax job ended normally")
    elif cause == channel.FaxSender.Cause.NOTFAX:
        print("the receiver was not a fax machine")
    else:
        print("the fax job failed")

Fax Details

class FaxDetails(channel, logger)

Holds details of the fax session. The details are filled in as the fax progresses.

ID

The fax ID as returned by the cloud.

line

The connected line associated with this fax.

fax_standard

T.30 or T.38.

options

The fax options, this is a dictionary in the form { option:value, … }.

failed_option

The fax options that could not be set, this is a dictionary in the form { option:value, … }.

pages

The number of fax pages sent or received so far.

last_page

Will be True if no more pages are to be handled during this fax session. Note: this does not imply that the fax session was successful.

negotiated

The fax parameters that have been negotiated, this is a dictionary in the form { option:value, … }.

raw_cause

The fax error code returned when the cause is ERROR or NOTFAX.

Usage example:

# create the fax document object
my_fax = FaxToSend('my_fax.tiff')
# send the fax and check the termination cause
if channel.FaxSender.send(fax_to_send=my_fax) != channel.FaxSender.Cause.NORMAL:
    # the fax did not terminate normally, look at the raw_cause
    print("Fax failed with raw cause {0}".format(channel.FaxSender.Details.raw_cause))