right  Talk To Us!

UAS API - Outbound Send Fax Sample Application

  • Filename:

    samples/outbound_send_fax.py

    Description:

    A sample application that will place a call and send a fax. The sample first creates a FaxToSend object which is the wrapper for the fax document. This object is used to read in two TIFF files to create the fax document to be sent. The first TIFF file is a header and the second is the body. Both TIFF files must already have been uploaded to the cloud. It is assumed that the name of the header file will be read from the application_parameters variable, which is configured on the Outbound Services page (Manage -> Outbound Services), and the name of the body is read from outbound_parameters.

    After creating the fax document object (my_fax = FaxToSend()), the header file is read in using the my_fax.set_content() function. Then the body is appended to by calling the my_fax.append() function. The application then demonstrates adding a page number to each page by configuring a page text object and then calling the my_fax.add_text_to_page() function on each page.

    The application now places the outbound call. The call destination and the call origin are supplied in outbound_parameters and application_parameters respectively (along with body and header in a semi-colon delimited string).

    The fax transmission is started by calling the channel.FaxSender.start() function and supplying a reference to the fax document object. The application then waits for the fax settings to be negotiated, channel.FaxSender.wait_for_negotiated_settings(), and prints them to the screen. It then uses channel.FaxSender.wait_for_next_page() to wait for each page to be sent, it does this until the last page has been indicated, and prints out the number of pages sent so far.

    Finally, the function channel.FaxSender.wait_until_finished() is used to wait until the fax session has completed. After that, the call is hung up.

    Code:

    """
    A simple example that will place a call and send a fax.
    
        Actions:
            - place a call
            - send a fax
            - hang up
    
    This sample uses two documents, a 'header' page and the
    fax 'body'. It is assumed that application_parameters is
    the name of the header page, and outbound_parameters is the
    name of the body.
    
    Several other assumptions are noted in the code comments.
    
    This application requires that call_from is supplied in 
    application_parameters (this is configured on the outbound 
    service page of the CWP). 
    
    For information on placing outbound calls please read the online 
    web services documentation.
    
    For additional information regarding outbound PSTN calls, please see the 
    online documentation.
    
    Also have a look at the invoke_outbound_service sample code in the 
    samples_ws directory.
    
    """
    
    from prosody.uas import Hangup, Error, FaxToSend, FaxToReceive
    
    __uas_identify__ = "application"
    __uas_version__  = "0.01b"
    
    def main(channel, application_instance_id, file_man, my_log, application_parameters, outbound_parameters):
        try:
            return_code = 0
    
            # in this sample the call origin and fax header name are given in application_parameters
            origin, fax_header = application_parameters.split(';')
            
            # get the call destination and the fax body name from outbound_parameters
            destination, fax_body = outbound_parameters.split(';')
            
            # This outbound application is going to send a fax, so we create
            # a FaxToSend object, known as a fax document object
            my_fax = FaxToSend()
    
            # Now set the content of the fax document object, this is read from
            # a TIFF media file which must be present on the cloud. In this case
            # the content is a fax header, to which more content will be added.
            cause = my_fax.set_content(fax_header)
    
            # The cause will be of type FileCause and should be checked.
            if cause != my_fax.FileCause.NORMAL:
                raise Error("failed to set fax content, cause is {0}".format(cause))
    
            # Add the main fax body to the document.
            cause = my_fax.append(fax_body)
            if cause != my_fax.FileCause.NORMAL:
                raise Error("failed to set fax content, cause is {0}".format(cause))
    
            # Add the page number to each page of the fax document.
            # First create a PageText object.
            page_text = my_fax.create_page_text()
    
            # We want the page number to be one inch from the top of the page.
            # So we set the unit of measurement to inches.
            page_text.Position.unit = page_text.Position.PagePositionUnits.INCHES
            page_text.Position.from_page_top = 1
    
            # We want the existing line at our pgae number position to be completely removed
            page_text.mode = page_text.PageTextMode.REPLACE
    
            # On each page put the page number on the left
            for i in range(my_fax.pages_to_send):
                page_text.left_text = 'This is page {0}'.format(i + 1)
                # page numbers start a 1
                cause = my_fax.add_text_to_page(i + 1, page_text)
                if cause != my_fax.FileCause.NORMAL:
                    raise Error("failed to set fax content, cause is {0}".format(cause))
    
            # Place the outbound call in the normal way
            if channel.call(destination, call_from=origin) != channel.State.ANSWERED:
                cause = channel.cause()
                raise Error("Call destination returned cause {0}".format(cause))
    
            # Now we can start sending the fax.
            if channel.FaxSender.start(fax_to_send=my_fax) is not True:
                cause = channel.FaxSender.cause()
                raise Error("fax sender failed to start sending the fax, cause is {0}.".format(cause))
    
            # The fax endpoints will negotiate the parameters for the fax session - which modem
            # and the modem speed, among other things. We can wait until these have been published
            # and then have a look. Note that the dictionary will be empty if fax negotiation fails.
            negotiated_settings = channel.FaxSender.wait_for_negotiated_settings()
            if negotiated_settings == {}:
                cause = channel.FaxSender.cause()
                if cause == channel.FaxSender.Cause.NOTFAX:
                    raise Hangup("The receiver was not a fax machine.")
                else:
                    raise Error("Fax negotiation failed with cause {0}".format(cause))
    
            my_log.debug("Negotiated Settings")
            for setting, value in negotiated_settings.items():
                my_log.debug("{0:>15.15} : {1}".format(setting, value))
    
            # Now 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()
                my_log.debug("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))
    
            # In faxing, it is the receiver that hangs up first, so it is polite
            # for the fax sender to wait for the other end to hang up.
            channel.wait_for_idle()
    
        except Hangup as exc:
            my_log.info("Hangup exception reports {0}".format(exc))
            return_code = -101
    
        except Error as exc:
            my_log.error("Error exception reports {0}".format(exc))
            return_code = -100
    
        except Exception as exc:
            my_log.exception("Got unexpected exception {0}".format(exc))
            return_code = -102
    
        finally:
            if channel.state() != channel.State.IDLE:
                channel.hang_up()
        return return_code
    
  • Filename:

    Samples\C#\OutboundSendFax\OutboundSendFax.cs

    Description:

    For this sample application, the 'Enable fax send' option needs to be ticked in the fax tab of your Outbound Service that will invoke it. Typically the default fax options provided will result in a fax being sent successfully. The Outbound Service may also specify in the applicationParameters the name of a .tif file that exists on the cloud, the first page of which is to be used as a header page for the sent fax.

    The content of the fax document to send is specified via the outboundParameters argument that originates from the entity that invoked the Outbound Service. This needs to be set to the name of a .tif file that exists on the cloud that contains 1 or more pages.

    The UASApplication object exposes the single fax document that can be sent on an outgoing call. The sample first sets the content of this document to be the 1st page of the file specified in the applicationParameters argument. It then appends all the pages from the content file specified in the outboundParameters argument. Finally, it adds some page number text to each page in the fax document.

    The sample then makes an outbound call using the destination and source addresses specified in applicationParameters and calls the channel.FaxSender.Send() method to send the fax. If successful this will return FaxCause.Normal. Note: this sample relies on the UAS framework to hang up the outbound call.

    Code:

    using System;
    using System.Threading;
    using AMSClassLibrary;
    using UASAppAPI;
    
    // An outbound application that makes a call to a destination address (passed in)
    // from a source address (passed in) and sends a fax to that call.
    //
    // The fax is constructed from a single header page and 1 or more content pages.
    // The header page is obtained from a .tif file specified in the service's application parameters.
    // The content pages are obtained from a .tif file specified in the outboundParameters.
    //
    // A page number is inserted into each page before sending.
    //
    // Fax sending can be enabled for a particular service by editing the service entry
    // from the Outbound Services (or Inbound Services) page for your platform. 
    //
    // If the destination address is a PSTN number then check the Outbound Calls documentation 
    // for your platform for details on requirements for source address.
    //
    // Requires:
    // [outboundParameters = destination address ; source address ; file name of fax]
    // [Fax Send to be enabled in the service invoking this application]
    // 
    // Optional:
    // [applicationParameters = file name (.tif) of header page]
    //
    // e.g. 
    // outboundParameters = "sip:bob@bobscompany.com;;ContractFax.tif"
    // or
    // outboundParameters = "441908081876;441908876543;ContractFax.tif"
    namespace OutboundSendFax
    {
        // The application class.
        // This must have the same name as the assembly and must inherit from either 
        // UASInboundApplication or UASOutboundApplication.
        // It must override the Run method.
        public class OutboundSendFax : UASOutboundApplication
        {
            // Possible return codes
            enum ReturnCode
            {
                // Success Codes:
                Success = 0,
    
                // Fail Codes:
                // -1 to -99 reserved
                ArgumentError = -100,
                FaxSendNotEnabled = -101,
                FaxSendFailed = -102
            }
    
            // This is the entry point for the application
            public override int Run(UASCallChannel channel,
                                    string applicationParameters, // fax header page file name (.tif) - optional
                                    string outboundParameters)    // destination address ; source address ; fax content file name (.tif)
            {
                this.Trace.TraceInfo("Start - appParms [{0}] outParms [{1}]",
                                   applicationParameters,
                                   outboundParameters);
                ReturnCode reply = ReturnCode.Success;
    
                // Check that fax sending has been enabled in the calling service.
                if (this.FaxDocumentToSend == null)
                {
                    this.Trace.TraceError("This app requires that fax sending is enabled in the calling service");
                    return (int)ReturnCode.FaxSendNotEnabled;
                }
    
                // Check we have been given a destination address, source address and fax content file name
                string[] splits = outboundParameters.Split(';');
                if (splits.Length < 3)
                {
                    this.Trace.TraceError("This app requires a destination address, source address and fax file name, in the outboundParameters field");
                    return (int)ReturnCode.ArgumentError;
                }
                string destinationAddress = splits[0];
                string sourceAddress = splits[1];
                string faxFileName = splits[2];
    
                // The fax header file may be empty
                string faxHeaderFileName = applicationParameters;
    
                // Format the fax to send
                if (!String.IsNullOrEmpty(faxHeaderFileName))
                {
                    // Set the first page to that in the header file
                    this.FaxDocumentToSend.SetContent(faxHeaderFileName, 1, 1);
                }
                // Append all pages from the contents file to the fax
                this.FaxDocumentToSend.Append(faxFileName);
    
                // Add page numbers to all pages, centred
                FaxPageText text = new FaxPageText(null, null, null);
                for (int page = 1; page <= this.FaxDocumentToSend.Details.PagesToSend; page++)
                {
                    text.CentreText = String.Format("[page {0}]", page);
                    this.FaxDocumentToSend.AddTextToPage(page, text, FaxPageTextMode.Insert);
                }
    
                // Set fax options:
                // Just set this end's subscriber id.
                // (this overrides any set in the service registration)
                FaxOptions options = new FaxOptions("SubscriberId", "5678");
    
                // Make a call
                CallState state = channel.Call(destinationAddress, sourceAddress);
                if (state == CallState.Answered)
                {
                    this.Trace.TraceInfo("Call answered");
    
                    // Now send the fax
                    this.Trace.TraceInfo("Sending fax {0}", faxFileName);
                    FaxCause cause = channel.FaxSender.Send(this.FaxDocumentToSend, options);
                    if (cause != FaxCause.Normal)
                    {
                        this.Trace.TraceError("Failed to send fax: cause {0}", channel.FaxSender.Cause.ToString());
                        reply = ReturnCode.FaxSendFailed;
                    }
                    else
                    {
                        // Sent ok, now retrieve some of the negotiated fax options
                        // used to send/receive the fax.
                        FaxOptions negotiatedOptions = this.FaxDocumentToSend.Details.NegotiatedOptions;
                        String receivingSubscriberId = negotiatedOptions["remotesubscriberid"];
                        this.Trace.TraceInfo("Sent fax to subscriber Id: {0}", receivingSubscriberId);
                    }
                }
    
                this.Trace.TraceInfo("Completed");
                return (int)reply;
            }
        }
    }
  • Filename:

    Samples\VB\OutboundSendFax\OutboundSendFax.vb

    Description:

    For this sample application, the 'Enable fax send' option needs to be ticked in the fax tab of your Outbound Service that will invoke it. Typically the default fax options provided will result in a fax being sent successfully. The Outbound Service may also specify in the applicationParameters the name of a .tif file that exists on the cloud, the first page of which is to be used as a header page for the sent fax.

    The content of the fax document to send is specified via the outboundParameters argument that originates from the entity that invoked the Outbound Service. This needs to be set to the name of a .tif file that exists on the cloud that contains 1 or more pages.

    The UASApplication object exposes the single fax document that can be sent on an outgoing call. The sample first sets the content of this document to be the 1st page of the file specified in the applicationParameters argument. It then appends all the pages from the content file specified in the outboundParameters argument. Finally, it adds some page number text to each page in the fax document.

    The sample then makes an outbound call using the destination and source addresses specified in applicationParameters and calls the channel.FaxSender.Send() method to send the fax. If successful this will return FaxCause.Normal. Note: this sample relies on the UAS framework to hang up the outbound call.

    Code:

    Imports System
    Imports System.Threading
    Imports System.Text
    Imports AMSClassLibrary
    Imports UASAppAPI
    
    ' An outbound application that makes a call to a destination address (passed in)
    ' from a source address (passed in) and sends a fax to that call.
    '
    ' The fax is constructed from a single header page and 1 or more content pages.
    ' The header page is obtained from a .tif file specified in the service's application parameters.
    ' The content pages are obtained from a .tif file specified in the outboundParameters.
    '
    ' A page number is inserted into each page before sending.
    '
    ' If the destination address is a PSTN number then check the Outbound Calls documentation 
    ' for your platform for details on requirements for source address.
    '
    ' Requires:
    ' [outboundParameters = destination address ; source address ; file name of fax]
    ' [Fax Send to be enabled in the service invoking this application]
    ' 
    ' Optional:
    ' [applicationParameters = file name (.tif) of header page]
    '
    ' e.g. 
    ' outboundParameters = "sip:bob@bobscompany.com;;ContractFax.tif"
    ' or
    ' outboundParameters = "441908081876;441908876543;ContractFax.tif"
    Namespace OutboundSendFax
    
        ' The application class.
        ' This must have the same name as the assembly and must inherit from either 
        ' UASInboundApplication or UASOutboundApplication.
        ' It must override the Run method.
        Public Class OutboundSendFax
            Inherits UASOutboundApplication
    
            ' Possible return codes
            Enum ReturnCode
                ' Success Codes:
                Success = 0
                ' ... any positive integer
    
                ' Fail Codes:
                ' -1 to -99 reserved
                ArgumentError = -101
                FaxSendFailed = -102
                FaxSendTimedOut = -103
            End Enum
    
            ' This is the entry point for the application
            Overrides Function Run(ByVal channel As UASCallChannel, _
                                   ByVal applicationParameters As String, _
                                   ByVal outboundParameters As String) _
                                   As Integer
    
                Me.Trace.TraceInfo("Start - appParms [{0}] outParms [{1}]", _
                                   applicationParameters, _
                                   outboundParameters)
                Dim reply As ReturnCode = ReturnCode.Success
    
                ' Check we have been given a destination address, source address and fax content file name
                Dim splits As String() = outboundParameters.Split(";")
                If splits.Length < 3 Then
                    Me.Trace.TraceError("This app requires a destination address, source address and fax file name, in the outboundParameters field")
                    Return ReturnCode.ArgumentError
                End If
                Dim destinationAddress = splits(0)
                Dim sourceAddress = splits(1)
                Dim faxFileName = splits(2)
    
                ' The fax header file may be empty
                Dim faxHeaderFileName = applicationParameters
    
                ' Format the fax to send
                If Not String.IsNullOrEmpty(faxHeaderFileName) Then
                    ' Set the first page to that in the header file
                    Me.FaxDocumentToSend.SetContent(faxHeaderFileName, 1, 1)
                End If
                ' Append all pages from the contents file to the fax
                Me.FaxDocumentToSend.Append(faxFileName)
    
                ' Add page numbers to all pages, centred
                Dim text As FaxPageText = New FaxPageText(Nothing, Nothing, Nothing)
                For page = 1 To Me.FaxDocumentToSend.Details.PagesToSend
                    text.CentreText = String.Format("[page {0}]", page)
                    Me.FaxDocumentToSend.AddTextToPage(page, text, FaxPageTextMode.Insert)
                Next page
    
                ' Make a call
                Dim state As CallState = channel.Call(destinationAddress, sourceAddress)
                If state = CallState.Answered Then
                    Me.Trace.TraceInfo("Call answered")
    
                    ' Now send the fax
                    Me.Trace.TraceInfo("Sending fax {0}", faxFileName)
                    Dim cause As FaxCause = channel.FaxSender.Send(Me.FaxDocumentToSend)
                    If Not cause = FaxCause.Normal Then
                        Me.Trace.TraceInfo("Failed to send fax: cause {0}", channel.FaxSender.Cause.ToString())
                        reply = ReturnCode.FaxSendFailed
                    End If
                End If
                
                Me.Trace.TraceInfo("Completed")
                Return reply
    
            End Function
    
        End Class
    
    End Namespace