GithubHelp home page GithubHelp logo

interfax / interfax-python Goto Github PK

View Code? Open in Web Editor NEW
12.0 5.0 13.0 82 KB

Fax send and receive in Python with the InterFAX REST API

Home Page: https://www.interfax.net/en/dev/python

License: MIT License

Python 97.82% HTML 0.28% Makefile 1.22% Dockerfile 0.67%
fax fax-api hipaa inbound interfax interfax-api library python online-fax outbound

interfax-python's Introduction

InterFAX Python Package

https://travis-ci.org/interfax/interfax-python.svg?branch=master

Installation | Getting Started | Contributing | Usage | License

Send and receive faxes in Python with the InterFAX REST API.

Installation

This package requires Python 2.7+. You can install it using:

pip install interfax

This module requires libmagic, for help installing on OSX or windows check the python-magic documentation.

Getting started

To send a fax from a PDF file:

from interfax import InterFAX

interfax = InterFAX(username="username", password="password")
fax = interfax.deliver(fax_number="+11111111112", files=["folder/fax.pdf"])
fax = fax.reload() # resync with API to get latest status
fax.status # Success if 0. Pending if < 0. Error if > 0

Usage

Client | Account | Outbound | Inbound | Documents | Helper Classes

Client

The client follows the 12-factor apps principle and can be either set directly or via environment variables.

# Initialize using parameters
interfax = InterFAX(username="...", password="...")

# Alternative: Initialize using environment variables
# * INTERFAX_USERNAME
# * INTERFAX_PASSWORD
interfax = InterFAX()

All connections are established over HTTPS.

Timeouts

The client takes a timeout parameter, this is a floating point number of seconds for the client to wait between receiving data before issuing a timeout error.

More: documentation <http://docs.python-requests.org/en/master/user/quickstart/#timeouts>

Account

Balance

Determine the remaining faxing credits in your account.

>>>  interfax.account.balance()
9.86

More: documentation

Outbound

Send fax | Get list | Get completed list | Get record | Get image | Cancel fax | Cancel fax | Search

Send fax

interfax.outbound.deliver(fax_number, files, **kwargs)

Submit a fax to a single destination number.

There are a few ways to send a fax. One way is to directly provide a file path or url.

# with a path
interfax.outbound.deliver(fax_number="+11111111112", files=["folder/fax.txt"])
# with a URL
interfax.outbound.deliver(fax_number="+11111111112", files=["https://s3.aws.com/example/fax.html"])

InterFAX supports over 20 file types including HTML, PDF, TXT, Word, and many more. For a full list see the Supported File Types documentation.

The returned object is a OutboundFax with just an id. You can use this object to load more information, get the image, or cancel the sending of the fax.

fax = interfax.outbound.deliver(fax_number="+11111111112", files=["fax.pdf"])
fax = fax.reload() # Reload fax, allowing you to inspect the status and more

fax.id        # the ID of the fax that can be used in some of the other API calls
fax.image()     # returns an image representing the fax sent to the fax_number
fax.cancel()    # cancel the sending of the fax

Alternatively you can create an File with binary data and pass this in as well.

with open("fax.pdf", "rb") as fp:
    f = interfax.files.create(fp.read(), mime_type="application/pdf")
interfax.outbound.deliver(fax_number="+11111111112", files=[f])

To send multiple files just pass in a list of strings and File objects.

interfax.outbound.deliver(fax_number="+11111111112", files=["fax.pdf", "https://s3.aws.com/example/fax.html"])

Under the hood every path and string is turned into a File object. For more information see the documentation for this class.

Keyword Arguments: contact, postpone_time, retries_to_perform, csid, page_header, reference, page_size, fit_to_page, page_orientation, resolution, rendering

More: documentation

Alias: interfax.deliver


Get outbound fax list

interfax.outbound.all(**kwargs)

Get a list of recent outbound faxes (which does not include batch faxes).

>>> interfax.outbound.all()
[OutboundFax(id=1), ...]
>>> interfax.outbound.all(limit=1)
[OutboundFax(id=1)]

Keyword Arguments: limit, last_id, sort_order, user_id

More: documentation


Get completed fax list

interfax.outbound.completed(*args)

Get details for a subset of completed faxes from a submitted list. (Submitted id's which have not completed are ignored).

>> interfax.outbound.completed(123, 234)
[OutboundFax(id=123), ...]

More: documentation


Get outbound fax record

interfax.outbound.find(fax_id)

Retrieves information regarding a previously-submitted fax, including its current status.

>>> interfax.outbound.find(123456)
OutboundFax(id=123456)

More: documentation


Get outbound fax image

interfax.outbound.image(fax_id)

Retrieve the fax image (TIFF file) of a submitted fax.

>>> image = interfax.outbound.image(123456)
Image(id=123456)
>>> image.data
"....binary data...."
>>> image.save("fax.tiff")
# saves image to file

More: documentation


Cancel a fax

interfax.outbound.cancel(fax_id)

Cancel a fax in progress.

interfax.outbound.cancel(123456)
=> true

More: documentation


Search fax list

interfax.outbound.search(**kwargs)

Search for outbound faxes.

>>> interfax.outbound.search(fax_number="+1230002305555")
[OutboundFax(id=1234), ...]

Keyword Arguments: ids, reference, date_from, date_to, status, user_id, fax_number, limit, offset

More: documentation

Inbound

Get list | Get record | Get image | Get emails | Mark as read | Resend to email

Get inbound fax list

interfax.inbound.all(**kwargs)

Retrieves a user's list of inbound faxes. (Sort order is always in descending ID).

interfax.inbound.all()
=> [InboundFax(id=1234), ...]
interfax.inbound.all(limit=1)
=> [InboundFax(id=1234)]

Keyword Arguments: unread_only, limit, last_id, all_users

More: documentation


Get inbound fax record

interfax.inbound.find(fax_id)

Retrieves a single fax's metadata (receive time, sender number, etc.).

>>> interfax.inbound.find(123456)
InboundFax(id=123456)

More: documentation


Get inbound fax image

interfax.inbound.image(fax_id)

Retrieves a single fax's image.

>>> image = interfax.inbound.image(123456)
Image(id=123456)
>>> image.data
"....binary data...."
>>> image.save("fax.tiff")
# saves image to file

More: documentation


Get forwarding emails

interfax.inbound.emails(fax_id)

Retrieve the list of email addresses to which a fax was forwarded.

interfax.inbound.email(123456)
[ForwardingEmail()]

More: documentation


Mark as read/unread

interfax.inbound.mark(fax_id, read=True)

Mark a transaction as read/unread.

interfax.inbound.mark(123456, read=True) # mark read
interfax.inbound.mark(123456, read=False) # mark unread

More: documentation


Resend inbound fax

interfax.inbound.resend(fax_id, email=None)

Resend an inbound fax to a specific email address.

>>> # resend to the email(s) to which the fax was previously forwarded
>>> interfax.inbound.resend(123456)
True
>>> # resend to a specific address
>>> interfax.inbound.resend(123456, email="[email protected]")
True

More: documentation


Documents

Create | Upload chunk | Get list | Status | Cancel

Document allow for uploading of large files up to 20MB in 200kb chunks. The File format automatically uses this if needed but a sample implementation would look as followed.

document = interfax.documents.create("test.pdf", os.stat("test.pdf").st_size)

with open("test.pdf", "rb") as fp:
    cursor = 0
    while True:
        chunk = fp.read(500)
        if not chunk:
            break
        next_cursor = cursor + len(chunk)
        document.upload(cursor, next_cursor-1, chunk)
        cursor = next_cursor

Create Documents

interfax.documents.create(name, size, **kwargs)

Create a document upload session, allowing you to upload large files in chunks.

>>> interfax.documents.create("large_file.pdf", 231234)
Document(id=123456)

Keyword Arguments: disposition, sharing

More: documentation


Upload chunk

interfax.documents.upload(id, range_start, range_end, chunk)

Upload a chunk to an existing document upload session.

>>> interfax.documents.upload(123456, 0, 999, "....binary-data....")
True

More: documentation


Get document list

interfax.documents.all(options = {})

Get a list of previous document uploads which are currently available.

>>> interfax.documents.all()
[Document(id=123456), ...]
>>> interfax.documents.all(offset=10)
[Document(id=123466), ...]

Keyword Arguments: limit, offset

More: documentation


Get document status

interfax.documents.find(id)

Get the current status of a specific document upload.

>>> interfax.documents.find(123456)
Document(id=123456)

More: documentation


Cancel document

interfax.documents.cancel(id)

Cancel a document upload and tear down the upload session, or delete a previous upload.

>>> interfax.documents.cancel(123456)
True

More: documentation


Helper Classes

OutboundFax

The OutboundFax is returned in most Outbound APIs. As a convenience the following methods are available.

fax = interfax.outbound.find(123)
fax = fax.reload() # Loads or reloads object
fax.cancel() # Cancels the fax
fax.image() # Returns an `Image` for this fax

InboundFax

The InboundFax is returned in some of the Inbound APIs. As a convenience the following methods are available.

fax = interfax.inbound.find(123)
fax = fax.reload() # Loads or reloads object
fax.mark(true) # Marks the fax as read/unread
fax.resend(email) # Resend the fax to a specific email address.
fax.image() # Returns an `Image` for this fax
fax.emails() # Returns a list of ForwardingEmail objects that the fax was forwarded on to

Image

A lightweight wrapper around the image data for a sent or received fax. Provides the following convenience methods.

image = interfax.outbound.image(123)
image.data # Returns the raw binary data for the TIFF image.
image.save("folder/fax.tiff") # Saves the TIFF to the path provided

File

This class is used by interfax.outbound.deliver and interfax.files to turn every URL, path and binary data into a uniform format, ready to be sent out to the InterFAX API.

It is most useful for sending binary data to the .deliver method.

>>> # binary data
>>> f = File(interfax, "....binary data.....", mime_type="application/pdf")
File()

>>> # Alternatively
>>> f = interfax.files.create("....binary data.....", mime_type="application/pdf")
>>> f.headers
{"Content-Type": "application/pdf"}
>>> f.body
"....binary data....."

interfax.outbound.deliver(fax_number="+1111111111112", files=[f])

Additionally it can be used to turn a URL or path into a valid object as well, though the .deliver method does this conversion automatically.

>>> # a file by path
>>> f = interfax.files.create("foo/bar.pdf")
>>> f.headers
{ "Content-Type": "application/pdf" }
>>> f.body
"....binary data....."

>>> # a file by url
>>> f = interfax.files.create("https://foo.com/bar.html")
>>> f.headers
{"Content-Location": "https://foo.com/bar.html"}
>>> f.body
None

ForwardingEmail

A light wrapper around the response received by asking for the forwarded emails for a fax.

fax = interfax.inbound.find(123)
email = fax.emails()[0]
email.email_address # An email address to which forwarding of the fax was attempted.
email.message_status # 0 = OK; number smaller than zero = in progress; number greater than zero = error.
email.completion_time # Completion timestamp.

Document

The Document is returned in most of the Document APIs. As a convenience the following methods are available.

document = interfax.documents.find(123)
document = document.reload() # Loads or reloads object
document.upload(0, 999, ".....binary data...." # Maps to the interfax.documents.upload method
document.cancel() # Maps to the interfax.documents.cancel method
document.id  # Extracts the ID from the URI (the API does not return the ID)

Contributing

  1. Fork the repo on GitHub
  2. Clone the project to your own machine
  3. Commit changes to your own branch
  4. Push your work back up to your fork
  5. Submit a Pull request so that we can review your changes

Tests

Before submitting a contribution please ensure all tests pass.

pip install tox # install tox
tox # run all tests

or

vagrant up
vagrant exec tox

License

This library is released under the MIT License.

interfax-python's People

Contributors

cbetta avatar danielknell avatar ricky-shake-n-bake-bobby avatar sdomininterfax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

interfax-python's Issues

does this send the hard Fax or efax?

Hi, I couldn't find any reference on the site or here if it is an eFax or actual fax that is sent to the received?
Can someone please clarify?
I will close the issue.

Shorten readme anchor text

Both for inbound and outbound the links are overflowing in the README.

screen shot 2016-10-07 at 21 07 12

In the Ruby library I just changed the text in the link to be different than that in the header.

screen shot 2016-10-07 at 21 08 33

Can we please do the same thing here?

Return more useful errors

In the ruby library I've tried to catch most errors and bubble them up in a meaningful way. For example when I send a fax to a number that I'm not yet allowed to send a fax to I get:

fax = interfax.deliver(faxNumber: "+11111111112", file: 'spec/test.pdf')

InterFAX::Client::BadRequestError: Bad request (400): {"code":-111,"message":"Attempting to fax to a number that is not the designated fax number in a developer account","moreInfo":null}

In this library I get

>>> fax = interfax.deliver(fax_number="+442084978650", files=["tests/test.pdf"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "interfax/outbound.py", line 20, in deliver
    files=self._generate_files(files))
  File "interfax/client.py", line 76, in post
    return self._request('POST', url, **kwargs)
  File "interfax/client.py", line 89, in _request
    return self._parse_response(request(method, url, **kwargs))
  File "interfax/client.py", line 117, in _parse_response
    response.raise_for_status()
  File "/Users/cbetta/.pyenv/versions/2.7.12/lib/python2.7/site-packages/requests/models.py", line 862, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://rest.interfax.net/outbound/faxes?faxNumber=%2B442084978650

Is Libmagic required?

@danielknell this pip library relies on libmagic it seems. I'm trying to decide if this is wise? What is this for? Can we work without it? Is it easy to install on every OS (including windows)?

If we do need it we should look at making this dependency clear in the docs.

Extract mimeType from retrieved image

Retrieved images can be .tiff or .pdf. In the ruby library we extract the mimeType from the response headers and pass it to the Image object.

https://github.com/interfax/interfax-ruby/blob/bb393008b079fc224eeef460b44dd463a709180f/lib/interfax/inbound.rb#L21

https://github.com/interfax/interfax-ruby/blob/bb393008b079fc224eeef460b44dd463a709180f/lib/interfax/client.rb#L107-L108

This was the user can query the file extension from the image object and use it to give it the right filename.

Allow to configure connection timeout and add default timeouts internally

http://docs.python-requests.org/en/master/user/quickstart/#timeouts

Although _request accepts kwargs, which could include optional timeout config

    def _request(self, method, url, **kwargs):
        """Make a HTTP request."""
        kwargs.setdefault('headers', {})
        kwargs['headers']['User-Agent'] = self.USER_AGENT
        kwargs['auth'] = (self.username, self.password)

        return self._parse_response(request(method, url, **kwargs))

reload which uses find doesn't allow to specify timeout nor sets it itself, thus causing requests to hang indefinitely.

client.outbound.completed(*ids) generates bad urls

When calling client.outbound.completed(*ids), the generated url has the IDs in a tuple:

>>> c.outbound.completed(123)
HTTPError: 400 Client Error: Bad Request for url: https://rest.interfax.net/outbound/faxes/completed?ids=%28123%2C%29
>>> c.outbound.completed(123,234)
HTTPError: 400 Client Error: Bad Request for url: https://rest.interfax.net/outbound/faxes/completed?ids=%28123%2C+234%29

This generated url does not conform with the API spec, where it should only be comma-separated, as:
https://rest.interfax.net/outbound/faxes/completed?ids=123%2C234

Error when submitting document

I get an error with the following code sample (with my own API keys and fax number)

from interfax import InterFAX
import os

interfax = InterFAX(
    username="username",
    password="password"
)

# create a new InterFAX Document
document = interfax.documents.create(
    "test.pdf",
    os.stat("test.pdf").st_size
)

# read the file to send
with open("test.pdf", "rb") as fp:
    cursor = 0
    while True:
        chunk = fp.read(500)
        if not chunk:
            break
        next_cursor = cursor + len(chunk)
        # upload each chunk
        document.upload(cursor, next_cursor-1, chunk)
        cursor = next_cursor

# send the fax
interfax.deliver(
  # a valid fax number
  fax_number="11222333444",
  # the document URI
  files=[document.uri]
)

The error is:

Traceback (most recent call last):
  File "extra_4_send_a_large_file_and_monitor_progress.py", line 34, in <module>
    files=[document.uri]
  File "/Users/cbetta/.pyenv/versions/3.5.3/lib/python3.5/site-packages/interfax/outbound.py", line 20, in deliver
    files=self._generate_files(files))
  File "/Users/cbetta/.pyenv/versions/3.5.3/lib/python3.5/site-packages/interfax/client.py", line 76, in post
    return self._request('POST', url, **kwargs)
  File "/Users/cbetta/.pyenv/versions/3.5.3/lib/python3.5/site-packages/interfax/client.py", line 89, in _request
    return self._parse_response(request(method, url, **kwargs))
  File "/Users/cbetta/.pyenv/versions/3.5.3/lib/python3.5/site-packages/interfax/client.py", line 117, in _parse_response

    response.raise_for_status()
  File "/Users/cbetta/.pyenv/versions/3.5.3/lib/python3.5/site-packages/requests/models.py", line 909, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://rest.interfax.net/outbound/faxes?faxNumber=11222333444

Any idea @danielknell ?

An exception occurred: 400 Client Error: Bad Request

Trying to send out a test fax and receiving this error.

An exception occurred: 400 Client Error: Bad Request for url: https://rest.interfax.net/outbound/faxes?faxNumber=%2B1xxxxxxxxxx

    interfax = InterFAX(username="username", password="password")
    fax = interfax.outbound.deliver(fax_number="+1xxxxxxxxxx", files=['test.pdf'])
    fax = fax.reload() # resync with API to get latest status
    fax.status # Success if 0. Pending if 0

where the x's represent the fax number

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.