Giter Site home page Giter Site logo

sailthru-python-client's Introduction

sailthru-python-client

For installation instructions, documentation, and examples please visit: http://getstarted.sailthru.com/new-for-developers-overview/api-client-library/python

A simple client library to remotely access the Sailthru REST API as per http://getstarted.sailthru.com/api

Python binding for Sailthru API based on Requests

It will make requests in JSON format.

Supports Python 2.6, 2.7, 3.3+

Installation (Tested with Python 2.7.x)

Installing with pip:

pip install sailthru-client

Running tests

Install tox and then type:

tox

API Rate Limiting

Here is an example how to check rate limiting and throttle API calls based on that. For more information about Rate Limiting, see Sailthru Documentation

sailthru_client = SailthruClient(api_key, api_secret)

# ... make some api calls ...

rate_limit_info = sailthru_client.get_last_rate_limit_info('user', 'POST')

# get_last_rate_limit_info returns None if given endpoint/method wasn't triggered previously
if rate_limit_info is not None:
    limit = rate_limit_info['limit'];
    remaining = rate_limit_info['remaining'];
    reset_timestamp = rate_limit_info['reset'];

    # throttle api calls based on last rate limit info
    if remaining <= 0:
         seconds_till_reset = reset_timestamp - time.time()
         # sleep or perform other business logic before next user api call
         time.sleep(seconds_till_reset);

sailthru-python-client's People

Contributors

elidickinson avatar eliwjones avatar expe avatar infynyxx avatar isaulv avatar joepikowski avatar kmike avatar marcelhamel avatar marissa-englander avatar mattdudys avatar maxenglander avatar mydagobah avatar neurodrone avatar peterzal avatar rcramblit avatar silverfix avatar sinneduy avatar smohapatra avatar terrycojones avatar wefarrell avatar ysimonson avatar zencephalon avatar

Stargazers

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

Watchers

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

sailthru-python-client's Issues

Have the library parse the JSON automatically

It'd be nice for library users if this library parsed the response JSON before returning it. For example, currently you have to do a json.loads(response) after every call to the API:

client = sailthru.SailthruClient(key, secret)
response = client.get_email('[email protected]')
response = json.loads(response)
if response.get('hardbounce'):
    # Handle hard-bounce email address

Because Sailthru returns JSON, it makes sense to return a parsed, Pythonic object rather than the raw JSON string, so the library user doesn't have to do this each time (or write their own wrapper to do it).

Somewhat related to issue 4, this should also probably happen for errors:

client = sailthru.SailthruClient(key, secret + 'wrong_secret')
try:
    response = client.get_email('[email protected]')
except sailthru.SailthruError as error:
    print error.code, error.message
    # Would print: "5 Signature hash does not match"

You have to check error on the response, not the encoded response

In receive_hardbounce_post the word error is checked against the entire response encoded as a string, but this is incorrect since the message might have the word "error" in it.

Instead, check the response object to see if it has an error attribute.

Instead of

        # for blasts
        if 'blast_id' in post_params:
            blast_id = post_params['blast_id']
            blast_response = self.get_blast(blast_id)
            try:
                blast_response = blast_response.get_body()
                blast_response = json.JSONEncoder().encode(blast_response)
                if 'error' in blast_response:
                    return False
            except json.decoder.JSONDecodeError:
                return False

should be

        # for blasts
        if 'blast_id' in post_params:
            blast_id = post_params['blast_id']
            blast_response = self.get_blast(blast_id)
            try:
                blast_response = blast_response.get_body()
                json.JSONEncoder().encode(blast_response)
            except json.decoder.JSONDecodeError:
                return False

no way to pass options to save_list

It does not seem possible to create a primary list with save_list since it does not offer any way to pass in options. Also it exposes an emails option which claims to populate a list with email addresses but doesn't seem to actually work for me and I don't see in the documentation.

Fix test_receive_verify_post in unit tests

When running unit tests, I see the following failure:

python test/test_sailthru_client.py 
.F...
======================================================================
FAIL: test_receive_verify_post (__main__.TestSailthruClient)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test/test_sailthru_client.py", line 74, in test_receive_verify_post
    self.assertEqual(actual, expected)
AssertionError: False != True

----------------------------------------------------------------------
Ran 5 tests in 0.001s

FAILED (failures=1)

It looks like there have been a few changes to the code but the unit tests have not been kept up to date. I've reordered some things in a PR I'll submit, but I'm not sure how necessary the json encoding line is.

Make errors bubble up / exceptions able to be caught

Unfortunately the exception handling in this library is more or less unusable. Because sailthru_http_request() catches exceptions and returns normally, there's no way to catch them in higher-level code.

Note that this is contrary to the documentation -- the try/catch in the example in README.md won't do anything, because those exceptions have been caught inside sailthru_http_request() already. In short, errors will either be silently ignored, or will bomb out when you do a json.loads() on the response.

I can see where this might be okay with HTTPError, because Sailthru returns JSON in the body. But certainly not for URLError -- that should either be bubbled up or re-raised as a sailthru Exception subclass. Returning str(e) is unhelpful and error prone.

For example, say the network is down or Python can't do the DNS lookup. With the current API:

>>> client = sailthru.SailthruClient(key, secret)
>>> client.get_email('[email protected]')
'<urlopen error [Errno 11004] getaddrinfo failed>'
# how do I check for this error without string parsing?

Ideally this would be something like:

>>> client = sailthru.SailthruClient(key, secret)
>>> try:
...     client.get_email('[email protected]')
... except sailthru.Error as error:
...     # Handle or log error
...     print "Couldn't get email info, error: ", error

As above, it's good practice for the a library to catch exceptions and re-raise them as an Exception subclass specific to that module. You can even subclass this again for things like JSONError, ConnectionError (for example).

See how our version handles this: https://github.com/oysterhotels/sailthru/blob/master/sailthru.py#L124

get_templates Fails

When calling the get_templates method it always errors

{'error': 99, 'errormsg': 'A valid template or template_id must be provided'}

Update required for SSLv3?

Should we do something due to Sailthru's email these days?

Sailthru:

POODLE SSL Update Required by 11/7
...
Developers, who are likely aware of this issue, should ensure that API integrations are upgraded away from SSLv3 as soon as possible, and absolutely before Nov. 7, 2014.

As of this moment I cannot tell whether this is an issue when using this module, i.e. requests.

SailthruClient.multi_send lacks schedule_time parameter

Hi all!

When trying to use SailthruClient.send and SailthruClient.multi_send interchangeably (depending on how many users I need to email), I've faced an issue related to the fact the two methods have different signatures.

The code looks roughly like this:

sc = SailthruClient(SAILTHRU_API_KEY, SAILTHRU_SECRET)
send_method = getattr(sc, 'multi_send' if isinstance(to_email, list) else 'send')
response = send_method(template_name, to_email, email_args, schedule_time=send_on)

You can see, that it raises TypeError: multi_send() got an unexpected keyword argument 'schedule_time' when to_email is a list.

My expectation was that send would be a proxy of multi_send, since the former is logically just a corner case of the latter. However, actually both methods turn out to implement almost identical code while having different signatures.

Is there a good reason why send differs from multi_send signature-wise and implementation of the two is not quite DRYish?

I'd be eager to submit a pull request with a fix if you found that reasonable.

Thanks,
Gennady

Breaking changes to save_template in 2.2.1

You changed the function signature of save_template from the following in 2.2.0

def save_template(self, template, template_fields=None):

to this in 2.2.1

def save_template(self, template, **template_fields):

That's actually kind of a big deal since it breaks most (all?) existing code that uses save_template. I'm guessing this was a mistake since it's uncommon to put breaking changes into a point release and there's nothing about it in CHANGES.

For example, we have code like:

response = sailthru_client.save_template(template_name, template_fields)

In 2.2.0 that works and in 2.2.1 it throws the exception save_template() takes exactly 2 arguments (3 given)

Worse, when we have code like:

response = sailthru_client.save_template(template=template_name, template_fields=template_fields)

In 2.2.0 that worked, but in 2.2.1 it silently fails to set all attributes of the blast besides its name.

stats_list is keyed off of long-text description instead of the more logical hash ID

Hello,

This is more of a pain point related to the design of the API rather than a question. Here is a snippet from my Python REPL:

>>> stats = sc.stats_list(list='valid_cryptic_looking_id_of_actual_list',date='2015-03-31')
>>> stats.get_body()['error']
99
>>> stats = sc.stats_list(list='long_text_description_of_that_same_list',date='2015-03-31')
>>> stats.get_body().keys()
[u'spam_loss_count', u'passive_count', u'source_count', u'lists_remove_count', u'email_count', u'optout_loss_count', u'count_time', u'disengaged_count', u'list', u'active_count', u'lists_count', u'dormant_count', u'signup_month', u'optout_count', u'engaged_count', u'spam_count', u'lists_signup_count', u'new_count', u'day', u'hardbounce_count']

I can use the API as it is but this is a suboptimal setup for a non-versioned API dealing with UTF-8 content, in my opinion.

Is there a way to make the API call with the guaranteed-to-be-ASCII hash ID instead of the long-text description?

Also, would you be open to versioning the API?

ssl SailthruClientError with python 2.7

Hi All,
After a bunch of successfull calls, the client calls fails with the following error. Digging this, I found that this might be an issue with the use of request module in sailthru_http_request method in sailthru_http.py.

File "../lib/python2.7/site-packages/sailthru/sailthru_client.py", line 678, in api_post return self._api_request(action, data, 'POST') File "../lib/python2.7/site-packages/sailthru/sailthru_client.py", line 710, in _api_request return self._http_request(self.api_url+'/'+action, self._prepare_json_payload(data), request_type) File "../lib/python2.7/site-packages/sailthru/sailthru_client.py", line 714, in _http_request return sailthru_http_request(url, data, method, file_data) File "../lib/python2.7/site-packages/sailthru/sailthru_http.py", line 47, in sailthru_http_request raise SailthruClientError(str(e)) SailthruClientError: EOF occurred in violation of protocol (_ssl.c:581) ERROR - EOF occurred in violation of protocol (_ssl.c:581)

Could you please look into this. We have tried this with the latest sailthru client version as well.

Thanks !!

Format of date literal in stats_list

def stats_list(self, list=None, date=None):

Which format does date have to be in? E.g. 03-04-2015, 20150403 etc.
The YYYYMMDD format appears to yield good results, but I'd like to have a clear cut statement from the devs.

Thanks.

increase request_timeout

We are using the python client and getting request timeout errors sometimes. could you please increase request_timeout in sailthru_http_request in sailthru_http.py. We require more then 10 minutes some time while dealing large data.
Attached the error am facing for reference :
image

Could use proxy feature.

Sailthru optionally takes whitelisted IP addresses. It may be beneficial to incorporate the proxies param inside of requests by adding it to the client class.

Don't use mutable default function arguments!

This is a fundamental aspect of Python and it introduces the potential for bad emailing errors for your customers. The mutable arguments are maintained across calls and re-used. Try googling python mutable arguments to functions.

'SailthruResponseError' object has no attribute 'msg'

Hi there,

reponse.get_error() only returns error code, but not the error message. However the error message does come through reponse.get_body().

>>> response.get_error().code
99
>>> response.get_error().msg
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'SailthruResponseError' object has no attribute 'msg'

Bug invoking stats_blasts with start_date and end_date

Hi,

the exact code is:

client = SailthruClient(api_key, secret)
start_date = '2009-01-01'
end_date = '2011-09-09'
client.stats_blast(start_date=start_date,end_date=end_date)

The error is:
{"error":5,"errormsg":"Signature hash does not match"}

Thanks.

github is behind pypi, how is this possible??

https://pypi.python.org/pypi/sailthru-client - is at version 2.1.1

master branch is at version 2.0.4: https://github.com/sailthru/sailthru-python-client/blob/master/setup.py#L4

latest tag is 2.1.0: https://files.app.net/3xnj2o7U.png

what should I use?
How do I know what is current, what's deprecated?

2.1.1 has no method save_user: https://files.app.net/3xngiX1K.png

BUT your github has that method: https://github.com/sailthru/sailthru-python-client/blob/master/sailthru/sailthru_client.py#L161-L169

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.