Python client library for Postmark API

Overview

Postmarker

Build Coverage Version Python versions Documentation Status Gitter License

Python client library for Postmark API.

Gitter: https://gitter.im/Stranger6667/postmarker

Installation

Postmarker can be obtained with pip:

$ pip install postmarker

Usage example

NOTE:

The attributes of all classes are provided as is, without transformation to snake case. We don't want to introduce new names for existing entities.

Send single email:

>>> from postmarker.core import PostmarkClient
>>> postmark = PostmarkClient(server_token='API_TOKEN')
>>> postmark.emails.send(
    From='[email protected]',
    To='[email protected]',
    Subject='Postmark test',
    HtmlBody='Hello dear Postmark user.'
)

Send batch:

>>> postmark.emails.send_batch(
    {
        'From': '[email protected]',
        'To': '[email protected]',
        'Subject': 'Postmark test',
        'HtmlBody': 'Hello dear Postmark user.',
    },
    {
        'From': '[email protected]',
        'To': '[email protected]',
        'Subject': 'Postmark test 2',
        'HtmlBody': 'Hello dear Postmark user.',
    }
)

Setup an email:

>>> email = postmark.emails.Email(
    From='[email protected]',
    To='[email protected]',
    Subject='Postmark test',
    HtmlBody='Hello dear Postmark user.'
)
>>> email['X-Accept-Language'] = 'en-us, en'
>>> email.attach('/home/user/readme.txt')
>>> email.attach_binary(content=b'content', filename='readme.txt')
>>> email.send()

There are a lot of features available. Check it out in our documentation! Here's just a few of them:

  • Support for sending Python email instances.
  • Bounces, Domains, Messages, Templates, Sender signatures, Status, Stats & Server API.
  • Django email backend.
  • Tornado helper.
  • Spam check API.
  • Wrappers for Bounce, Inbound, Open and Delivery webhooks.

Documentation

You can view the documentation online at:

Or you can look at the docs/ directory in the repository.

Python support

Postmarker supports Python 3.6 - 3.9 and PyPy3.

Thanks

Many thanks to Shmele and lobziik for their reviews and advices :)

Comments
  • TypeError for SafeMIMEText

    TypeError for SafeMIMEText

    Follow up for this comment:

    @Stranger6667 Is this working for you? I am getting the same exception with Python 2.7, Django 1.11 as well as Python 3.6, Django 1.11.

    I get

    TypeError: Object of type 'SafeMIMEText' is not JSON serializable and I am unable to debug the issue.

    Hi @suriya ! Could you, please, add some code to reproduce the issue?

    opened by Stranger6667 9
  • Send Tag information via the Django interface

    Send Tag information via the Django interface

    I can't figure out a way to send Tag information to Postmark when using the Django EmailBackend. I did dive deep into the code but unfortunately had difficulty figuring out where the right place even to patch it would be.

    I know I could use the regular PostmarkClient, but it's important for us to continue using the built-in Django mechanism so that we can stay vendor agnostic.

    Can you point me in the right direction on where a patch would go?

    opened by jdotjdot 8
  • Remove dependency on mock

    Remove dependency on mock

    Postmarker has a dependency on mock, used here: https://github.com/Stranger6667/postmarker/blob/c0c0f7af623dc7b3fc0c030867773755dca31f67/postmarker/_compat.py#L13

    I notice that mock.patch is used only in tests. Does this make sense to move the line to a separate file _compat_tests.py so that normal usage of postmarker does not need the mock package?

    opened by suriya 7
  • Action required: Upcoming TLS configuration changes

    Action required: Upcoming TLS configuration changes

    Thank you so much for your work here!

    Just wanted to confirm if this package will be affected by the Postmark upcoming TLS configuration changes?

    The email below was received just a few hours ago:

    Hi there, To ensure the continued security of our systems, we wanted to let you know about some upcoming changes to our TLS (Transport Layer Security) configurations for API access.These changes may affect your application’s ability to continue to send mail through Postmark, so please read through this email in detail. You can also read through these changes on our website.These changes do not affect sending via SMTP.

    What’s changingOn April 13, 2021, we are going to (1) disable TLSv1 access, (2) disable all RC4 and low-strength ciphers, and (3) add HSTS headers.Here’s the full timeline of the changes:February 2021: Announcement of the changes, and testing endpoints are made available.March 23, 2021: Perform “blackout” test, where we cut over to the new configuration for one hour in production.March 30, 2021: Perform another “blackout” test, where we cut over to the new configuration for 12 hours in production.April 13, 2021: Cut over production to new configuration permanently.April 20, 2021: Decommission temporary testing SSL endpoint.We’ll discuss each change below, as well as your next steps to make sure sending isn’t interrupted. Changes and impact(1) Disabling TLSv1 accessTLSv1 has been deprecated, and we are following suit.Impact: Connections that only support TLSv1 would not be able to connect anymore after this change.(2) Disabling all RC4 and low-strength ciphersRC4 ciphers are considered weak and they are deprecated as well. Along with this, we are getting rid of any low-strength ciphers that are vulnerable to breaks as well.Impact: Connections that only support these old/weak ciphers would not be able to connect anymore after this change.(3) Adding HSTS headersHSTS (HTTP Strict Transport Security) headers tell web clients to only ever connect to a URL over HTTPS for a period of time (usually 6 months to 1 year). This prevents something called a “downgrade attack”, where users are tricked into visiting a version of a URL that is not secured or validated with TLS.Impact: We are adding these headers in accordance with industry standards. There is no API connectivity impact. ----- | -----

    What you need to doIf you send with Postmark via our API, please make sure that your sending infrastructure is able to deal with these changes prior to the April 13 cutover date.We’ve set up a temporary endpoint at api-ssl-temp.postmarkapp.com that has these changes already applied. You can use this as an endpoint to test/validate against. Please be aware that there is no expectation of uptime on this endpoint, and that it will be shut down on April 20, 2021 with no further notice. It should only be used for temporary testing of non-production traffic.If any of your tests with the temporary endpoint fail, updating your OpenSSL library should resolve the issue. If you are having trouble getting your API integration to work with this temporary endpoint, please contact our support team and let us know the exact error message encountered when attempting to connect, and a log of the connection attempt. We may be able to provide specific instructions for using newer TLS configurations.If you have any questions, just reply to this email. We’re here to help!

    opened by v-ken 5
  • Documentation is outdated on ReadTheDocs

    Documentation is outdated on ReadTheDocs

    Unfortunately the docs at https://postmarker.readthedocs.io/en/stable/ are stuck on 1.3.0.

    Looking at the changes since then (see https://github.com/Stranger6667/postmarker/compare/0.13.0...v0.17.1), I'm not too sure what could have caused this, but I know RTD to be quite picky about docs dependencies, so maybe the move to pyproject.toml?

    opened by loicteixeira 4
  • send_with_template won't allow alias

    send_with_template won't allow alias

    Referring to #150

    When I try to send an email using a template alias, postmark.emails.send_with_template(TemplateAlias=alias, TemplateModel=model, To=sendto, From=efrom)

    I get the following response: TypeError: send_with_template() missing 1 required positional argument: 'TemplateId'

    Thanks.

    opened by 2x2xplz 4
  • Django backend crashes when sending a message with attachments

    Django backend crashes when sending a message with attachments

    Postmarker's Django backend crashes when sending a message with attachments. The crash happens when therequests library tries to convert a dictionary containing email message information into a JSON string. The conversion fails for attachments.

    Here's a stack trace.

      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/django/core/mail/message.py", line 303, in send
        return self.get_connection(fail_silently).send_messages([self])
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/django.py", line 57, in send_messages
        response = self.client.emails.send_batch(*prepared_messages, TrackOpens=self.get_option('TRACK_OPENS'))
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/models/emails.py", line 324, in send_batch
        return self.EmailBatch(*emails).send(**extra)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/models/emails.py", line 245, in send
        responses = [self._manager._send_batch(*batch) for batch in chunks(emails, self.MAX_SIZE)]
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/models/emails.py", line 268, in _send_batch
        return self.call('POST', '/email/batch', data=emails)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/models/base.py", line 63, in call
        return self.client.call(*args, **kwargs)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/core.py", line 84, in call
        **kwargs
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/postmarker/core.py", line 106, in _call
        response = self.session.request(method, url, json=data, params=kwargs, headers=default_headers)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/requests/sessions.py", line 474, in request
        prep = self.prepare_request(req)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/requests/sessions.py", line 407, in prepare_request
        hooks=merge_hooks(request.hooks, self.hooks),
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/requests/models.py", line 305, in prepare
        self.prepare_body(data, files, json)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/requests/models.py", line 462, in prepare_body
        body = complexjson.dumps(json)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/simplejson/__init__.py", line 280, in dumps
        def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/simplejson/encoder.py", line 291, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/simplejson/encoder.py", line 373, in iterencode
        return _iterencode(o, 0)
      File "/home/vagrant/bookshelf.git/my-env/local/lib/python2.7/site-packages/simplejson/encoder.py", line 268, in default
        raise TypeError(repr(o) + " is not JSON serializable")
    TypeError: <django.core.mail.message.SafeMIMEText instance at 0x7f15eacc8e18> is not JSON serializable
    
    opened by suriya 4
  • Unable to handle Unicode in message body using API

    Unable to handle Unicode in message body using API

    Sorry to be leaving you so many issues!

    Looks like there's now an issue when sending messages at least with unicode characters in the body. The message I am sending usings django.template.Template to render a template to a string and then submit it as the message HTML body.

    This problem goes away if you temporarily set sys.setdefaultencoding('utf8') (which you obviously shouldn't be doing).

    Here is the traceback:

    /Users/../utils/emails.pyc in send_html_email(subject, from_email, to_emails, reply_to, text_body, html_body, headers, tag, metadata, subaccount, attachments, send_in, extra_params, bcc)
        128             setattr(msg, key, value)
        129
    --> 130     msg.send()
        131
        132
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/django/core/mail/message.pyc in send(self, fail_silently)
        340             # send to.
        341             return 0
    --> 342         return self.get_connection(fail_silently).send_messages([self])
        343
        344     def attach(self, filename=None, content=None, mimetype=None):
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/django.pyc in send_messages(self, email_messages)
         55             client_created = self.open()
         56             prepared_messages = [self.prepare_message(message) for message in email_messages]
    ---> 57             response = self.client.emails.send_batch(*prepared_messages, TrackOpens=self.get_option('TRACK_OPENS'))
         58             msg_count = len(response)
         59             if client_created:
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/models/emails.pyc in send_batch(self, *emails, **extra)
        322         :param extra: dictionary with extra arguments for every message in the batch.
        323         """
    --> 324         return self.EmailBatch(*emails).send(**extra)
        325
        326     # NOTE. The following methods are included here to expose better interface without need to import relevant classes.
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/models/emails.pyc in send(self, **extra)
        242         :rtype: `list`
        243         """
    --> 244         emails = self.as_dict(**extra)
        245         responses = [self._manager._send_batch(*batch) for batch in chunks(emails, self.MAX_SIZE)]
        246         return sum(responses, [])
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/models/emails.pyc in as_dict(self, **extra)
        220         :return: List of dictionaries.
        221         """
    --> 222         return [self._construct_email(email, **extra) for email in self.emails]
        223
        224     def _construct_email(self, email, **extra):
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/models/emails.pyc in _construct_email(self, email, **extra)
        229             email = Email(manager=self._manager, **email)
        230         elif isinstance(email, (MIMEText, MIMEMultipart)):
    --> 231             email = Email.from_mime(email, self._manager)
        232         elif not isinstance(email, Email):
        233             raise ValueError
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/models/emails.pyc in from_mime(cls, message, manager)
        178         """
        179         if isinstance(message, MIMEMultipart):
    --> 180             text, html, attachments = deconstruct_multipart(message)
        181         else:
        182             text, html, attachments = message.get_payload(decode=True).decode(), None, []
    
    /Users/../.virtualenvs/TCJ/lib/python2.7/site-packages/postmarker/models/emails.pyc in deconstruct_multipart(message)
         85             text = part.get_payload(decode=True).decode()
         86         elif content_type == 'text/html':
    ---> 87             html = part.get_payload(decode=True).decode()
         88         elif content_type != 'multipart/alternative':
         89             attachments.append(part)
    
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 3495: ordinal not in range(128)
    

    I'm currently getting around this with the following context manager, but obviously this cannot be the case long-term:

    @contextlib.contextmanager
    def set_default_encoding(encoding='ascii'):
        """\
        Temporarily set the default encoding within the span of the context.
    
        NOTE: Using `sys.setdefaultencoding()` is HIGHLY DISCOURAGED and this context
        manager should only be used when working with third party libraries that incorrectly
        handle unicode/strings/bytestrings and cannot easily be patched, updated, or worked around.
        """
        import sys
        reload(sys)
        original_encoding = sys.getdefaultencoding()
        sys.setdefaultencoding(encoding)
        yield
        sys.setdefaultencoding(original_encoding)
    
    opened by jdotjdot 4
  • Library incorrectly quotes long lines when sent via API

    Library incorrectly quotes long lines when sent via API

    If large HTML files (particularly those with large lines, for example anything produced using MJML with the --min minification flag enabled) are sent using Postmarker, the HTML is escaped using quoted-printable and sent to Postmark's API that way, when it should actually be sent unquoted.

    The reason this happens is under the hood, Postmarker calls the Django email backend's message.message() within EmailBackend.prepare_message(). This has the message turn itself into MIME, which then is later deconstructed back to a dict using Email.from_mime(). Since Django thinks it's serializing the email for an SMTP send, it automatically quotes the email or alternative attachment under certain circumstances (utf-8 + long lines, see django.core.mail.message.py:220) and sets the Content-Transfer-Encoding to quoted-printable. When Postmarker turns that back into a dict, it loses the Content-Transfer-Encoding header and does not unquote, leading to the quoted version being sent directly via Postmark's API and completely incorrect emails being sent, particularly if they include any Outlook-specific markup that uses XML namespaces and colons.

    One way to fix this is when converting the MIME email back to a dictionary, to detect if it has been quoted and then to unquote using email.quoprimime.body_decode(...). Alternatively, the better way to fix this is to refactor simply not to let Django's mailing backend create the MIME email at all, and simply send the body and headers to Postmark via the API without doing any unnecessary processing. This is how djrill for Mandrill works, and emails I sent with Postmarker that got mangled were not mangled with djrill.

    opened by jdotjdot 4
  • Django 4.0 incompatibilities

    Django 4.0 incompatibilities

    Django release 4.0 has introduced some incompatibilities but they are all quite benign.

    1. django/utils/encoding#force_text has been removed. It was previously deprecated.

    force_str can be used as a direct replacement and was aliased. Available since Feb 2019 https://github.com/django/django/commit/3bb6a4390c0a57da991fcb1c0642b9b3fccff751

    force_text was deprecated shortly after in https://github.com/django/django/commit/d55e88292723764a16f0689c73bc7e739dfa6047

    force_text was then removed in the v4 release cycle as per the deprecation notice https://github.com/django/django/commit/810f037b29402f848a766f6900b4ebfbaf64cc88

    1. Signal has lost the provided_args initialiser argument

    This argument was deprecated in Mar 2020 at https://github.com/django/django/commit/769cee525222bb155735aba31d6174d73c271f3c

    And subsequently removed in Jan 2021 at https://github.com/django/django/commit/1adcf20385c2856d3655089ff7a0b55b32e5587a

    I don't know which previous versions of Django this affects or how backwards compatible you want to be, but I'll post a RP with these changes to run through Django v4.0

    opened by robshep 3
  • Update domains verification methods

    Update domains verification methods

    Postmark deprecated verifyspf (see https://postmarkapp.com/blog/why-we-no-longer-ask-for-spf-records).

    This PR:

    • Updates the test case for verifyspf to reflect this (ie. SPFVerified is always True)
    • Introduces 2 new methods for verifyDkim and verifyReturnPath API endpoints
    opened by n11c 3
  • fix: expose `on_exception` with other Django signals

    fix: expose `on_exception` with other Django signals

    on_exception is missing from src/postmarker/django/__init__.py, making it impossible to do

    from postmarker.django import on_exception
    

    even though the pre_send and post_send signals are exposed in this way.

    Thanks

    opened by gregsadetsky 0
  • Suggestion: better documentation of `emails` parameter for send_batch and send_template_batch

    Suggestion: better documentation of `emails` parameter for send_batch and send_template_batch

    The documentation for send_batch and send_template_batch both mention:

    Parameters emails – Email instances or dictionaries

    However, emails is actually equivalent to *args, i.e. emails internally captures (within send_batch and send_template_batch) all arguments passed to the function. The variable name emails is not actually exposed to the caller, and so isn't properly a "parameter".

    Calling:

    postmark.emails.send_batch(emails=[email, another_email])
    

    will not work -- the function will instead confusingly return an empty array.

    Just in case anybody comes here to troubleshoot this, the correct way to call the functon is rather:

    postmark.emails.send_batch(email, another_email)
    # ... or alternatively ...
    my_emails = [email, another_email]
    postmark.emails.send_batch(*my_emails)
    

    Thanks!

    opened by gregsadetsky 1
  • Suggestion: better string representation of Email object

    Suggestion: better string representation of Email object

    After creating an Email object, converting it to a string representation leads to a confusing output.

    Example:

    e = postmark_client.emails.Email(From="[email protected]", To="[email protected]", TextBody="text")
    print(e)
    

    This outputs <Email: None>

    Cheers

    opened by gregsadetsky 0
  • Offset / count invariant when you have more than 10,000 messages

    Offset / count invariant when you have more than 10,000 messages

    Hi there,

    Thanks for a great library. I'm running into an edge case. If you have more than 10,000 outbound messages, this library will break as the count=None loop will eventually send a request like so:

    https://api.postmarkapp.com/messages/outbound?count=500&offset=10000

    And per Postmark's docs, the max of count + offset = 10,000.

    So you'll get a 500 error from them.

    This isn't an issue if the TotalCount in base.py returns less 10,000 because you'll break out of the loop.

    I'm not sure how best to handle this. It seems like, no matter what we do, we can't get to message 10,001+ on postmark. So maybe the loop should also just break at 10,000.

    Hope that helps. Thanks again for your work!

    opened by silviogutierrez 0
  • Cant attach csv file with UTF-8

    Cant attach csv file with UTF-8

    Hello, I attach csv file with unicode string and send to email with postmark. When I download csv file and open with ms excel the file show wrong string. Not sure what I do wrong ?

            files = []
            csvfile = StringIO()
            writer = csv.writer(csvfile)
            writer.writerow(['some unicode string'])
    
            data = csvfile.getvalue()
            attachment = MIMEBase('text', 'csv')
            attachment.set_payload(data.encode('utf-8'))
            encoders.encode_base64(attachment)
            attachment.add_header('Content-Disposition', 'attachment', filename='readme.csv')
            files.append(attachment)
            
            email = postmark.emails.send_with_template(
                TemplateId=xxx,
                TemplateModel={},
                From='[email protected]',
                To=['[email protected]'],
                Attachments=files
            )
    
    opened by dogrocker 1
Releases(v1.0)
  • v1.0(Jan 15, 2022)

  • v0.18.2(Jun 3, 2021)

    :rocket: Features

    • 288dfe5 Support subject search

    :wrench: Chores and Improvements

    • 92078ef Release 0.18.2

    :package: Other

    • e2c6f1a Fix missing link
    Source code(tar.gz)
    Source code(zip)
  • v0.18.1(May 13, 2021)

  • v0.18.0(May 11, 2021)

    :rocket: Features

    • 33bf3b6 add support for batchWithTemplates

    :wrench: Chores and Improvements

    • a056ae4 Release 0.18.0
    • 1378c30 Update pre-commit hooks

    :package: Other

    • e8dda64 Add a changelog entry
    Source code(tar.gz)
    Source code(zip)
  • v0.17.1(Mar 2, 2021)

    :rocket: Features

    • 37af8e9 root_api_url argument for PostmarkClient

    :wrench: Chores and Improvements

    • f46d0eb Release 0.17.1

    :package: Other

    • a86e138 Fix sphinx warnings
    Source code(tar.gz)
    Source code(zip)
  • v0.17.0(Dec 22, 2020)

    :bug: Bug fixes

    • c64348a Make TemplateID not required if TemplateAlias is specified

    :wrench: Chores and Improvements

    • f759727 Release 0.17.0
    • 78fc83c Drop support for Python 3.5

    :package: Other

    • 830462f Merge pull request #191 from Stranger6667/dd/template-alias-fix

    fix: Make TemplateID not required if TemplateAlias is specified

    Source code(tar.gz)
    Source code(zip)
  • v0.16.0(Nov 10, 2020)

    :rocket: Features

    • a96cac8 Implement MessageStream support

    :wrench: Chores and Improvements

    • c42f1e3 Release 0.16.0
    • 814e3c4 Remove obsolete setup.cfg

    :package: Other

    • af4731d Add missing release notes
    • 669189c Add CODE_OF_CONDUCT.md
    Source code(tar.gz)
    Source code(zip)
  • v0.15.0(Aug 30, 2020)

    :wrench: Chores and Improvements

    • 59871c9 Release 0.15.0
    • a4211f9 Add gitter link
    • edcf364 Add gitter link
    • 5bf9865 Move to src layout
    • d7b92a1 Drop another Python 2 shim
    • 754296a Remove Python 2 shims
    • 3aba8be Apply pylint
    • 5cccb4d Add exception chaining
    • 5c7db7b Apply pre-commit & add GitHub Action job for pre-commit

    :package: Other

    • 9c6e278 Add release job

    • 48080f6 Add GitHub Actions build for Python 3.5-3.9 and PyPy3

    • 415ece4 Drop support for Python 2.7, 3.3, 3.4, PyPy2 and Jython.

    • db20b64 Drop Travis CI

    • 03f4cdf Create FUNDING.yml

    • dd1065f Release 0.14.1

    • 741bbf1 Add missing changelog entry

    • 618d628 Merge remote-tracking branch 'origin/master'

    • 1710940 Code black.

    • b3efc2f At the moment, using the EmailTemplate() doesn't allow Metadata parameters.

    EmailTemplate() now accept Metadata parameters.

    e.g.

    postmark.emails.EmailTemplate(
    	TemplateId=template_id,
    	TemplateAlias=template_alias,
    	From=f"{from_name} {from_}",
    	To=user.email,
    	Headers={"X-Accept-Language": "en-us, en"},
    	TemplateModel=template_model,
    	Metadata=metadata
    )
    
    Source code(tar.gz)
    Source code(zip)
  • v0.14.1(Mar 31, 2020)

  • v0.14.0(Mar 31, 2020)

  • v0.13.1(Mar 31, 2020)

  • 0.13.0(Nov 25, 2018)

    Added

    • Support for Python 3.7. #170
    • Support for Metadata option. #168

    Changed

    • Stream logs to sys.stdout by default. #159

    Removed

    • Support for Python 2.6, 3.2 and 3.3.
    Source code(tar.gz)
    Source code(zip)
  • 0.12.2(Nov 5, 2018)

  • 0.12.1(Nov 5, 2018)

  • 0.12.0(Jun 12, 2018)

    Added

    • Support for TemplateAlias. #150

    Fixed

    • Processing of alternatives together with attachments. #148
    • Processing of message/rfc822 attachments.
    Source code(tar.gz)
    Source code(zip)
  • 0.11.3(Nov 8, 2017)

  • 0.11.2(May 14, 2017)

  • 0.11.1(May 10, 2017)

  • 0.11.0(May 2, 2017)

    • message property for Bounce, Delivery and Open classes to access corresponding OutboundMessage instance. #119
    • An ability to control timeout and retries behaviour. #82
    • Signal for exceptions in Django backend. #126
    • Tornado helper. #85
    Source code(tar.gz)
    Source code(zip)
  • 0.10.1(Apr 3, 2017)

  • 0.10.0(Mar 30, 2017)

    Added

    • Short-circuit send of empty batches in Django backend. #123

    Changed

    • OutboundMessageManager.get_details and InboundMessageManager.get_details were methods were renamed to get. Now they returns OutboundMessage and InboundMessage instances respectively. #125
    • Renamed token kwarg in PostmarkClient to server_token. #130

    Fixed

    • Fix counting of successfully sent messages in Django backend. #122
    • Propagate API exceptions in Django backend. #128
    Source code(tar.gz)
    Source code(zip)
  • 0.9.2(Mar 29, 2017)

  • 0.9.1(Mar 29, 2017)

  • 0.9.0(Mar 28, 2017)

    • Added an ability to load all items without specifying exact count value. #106
    • Added delivery webhook wrapper. #95
    • Added open webhook wrapper. #96
    • Added bounce webhook wrapper. #97
    • Fixed PyPI package display. #116

    Changed

    • postmarker.webhooks.InboundWebhook class was superseded by postmark.messages.inbound.InboundMessage constructor, which works in the same way.
    Source code(tar.gz)
    Source code(zip)
  • 0.8.1(Mar 15, 2017)

  • 0.8.0(Mar 13, 2017)

    • Added an ability to download more than 500 items. #70
    • Added pre_send and post_send Django signals. #83
    • Inbound rules triggers API. #75
    • Changed logs output stream to default sys.stderr. #102
    • Tags triggers API. #74
    Source code(tar.gz)
    Source code(zip)
  • 0.7.2(Mar 11, 2017)

  • 0.7.1(Mar 10, 2017)

  • 0.7.0(Mar 2, 2017)

  • 0.6.2(Jan 3, 2017)

Owner
Dmitry Dygalo
Building a platform for effortless API testing
Dmitry Dygalo
Python API Client for Twitter API v2

?? Python Client For Twitter API v2 ?? Why Twitter Stream ? Twitter-Stream.py a python API client for Twitter API v2 now supports FilteredStream, Samp

Twitivity 31 Nov 19, 2022
Dns-Client-Server - Dns Client Server For Python

Dns-client-server DNS Server: supporting all types of queries and replies. Shoul

Nishant Badgujar 1 Feb 15, 2022
Raphtory-client - The python client for the Raphtory project

Raphtory Client This is the python client for the Raphtory project Install via p

Raphtory 5 Apr 28, 2022
Pure Python 3 MTProto API Telegram client library, for bots too!

Telethon ⭐️ Thanks everyone who has starred the project, it means a lot! Telethon is an asyncio Python 3 MTProto library to interact with Telegram's A

LonamiWebs 7.3k Jan 1, 2023
Python client library for Google Maps API Web Services

Python Client for Google Maps Services Description Use Python? Want to geocode something? Looking for directions? Maybe matrices of directions? This l

Google Maps 3.8k Jan 1, 2023
Python client library for Bigcommerce API

Bigcommerce API Python Client Wrapper over the requests library for communicating with the Bigcommerce v2 API. Install with pip install bigcommerce or

BigCommerce 81 Dec 26, 2022
Backlog API v2 Client Library for Python

BacklogPy - Backlog API v2 Client Library for Python BacklogPy is Backlog API v2 Client Library for Python 2/3 Install You can install the client libr

Koudai Aono 7 Dec 16, 2022
Python API client library for phpIPAM installations

phpypam: Python API client library for phpIPAM installation As we started to develop phpipam-ansible-modules we used an existing python library for ph

codeaffen 3 Aug 3, 2022
Drcom-pt-client - Drcom Pt version client with refresh timer

drcom-pt-client Drcom Pt version client with refresh timer Dr.com Pt版本客户端 可用于网页认

null 4 Nov 16, 2022
A client library for the REST API of DocuWare's DMS

docuware-client This is a client library for the REST API of DocuWare DMS. Since DocuWare's documentation regarding the REST API is very sparse (at th

Stefan Schönberger 1 Feb 23, 2022
Official Python client for the MonkeyLearn API. Build and consume machine learning models for language processing from your Python apps.

MonkeyLearn API for Python Official Python client for the MonkeyLearn API. Build and run machine learning models for language processing from your Pyt

MonkeyLearn 157 Nov 22, 2022
🖥️ Python - P1 Monitor API Asynchronous Python Client

??️ Asynchronous Python client for the P1 Monitor

Klaas Schoute 9 Dec 12, 2022
alpaca-trade-api-python is a python library for the Alpaca Commission Free Trading API.

alpaca-trade-api-python is a python library for the Alpaca Commission Free Trading API. It allows rapid trading algo development easily, with support for both REST and streaming data interfaces

Alpaca 1.5k Jan 9, 2023
Python API Client for Close

Close API A convenient Python wrapper for the Close API. API docs: http://developer.close.com Support: [email protected] Installation pip install clos

Close 56 Nov 30, 2022
Python client for CoinPayments API

pyCoinPayments - Python API client for CoinPayments Updates This library has now been converted to work with python3 This is an unofficial client for

James 27 Sep 21, 2022
DEPRECATED - Official Python Client for the Discogs API

⚠️ DEPRECATED This repository is no longer maintained. You can still use a REST client like Requests or other third-party Python library to access the

Discogs 483 Dec 31, 2022
The Foursquare API client for Python

foursquare Python client for the foursquare API. Philosophy: Map foursquare's endpoints one-to-one Clean, simple, Pythonic calls Only handle raw data,

Mike Lewis 400 Dec 19, 2022
Python Client for Instagram API

This project is not actively maintained. Proceed at your own risk! python-instagram A Python 2/3 client for the Instagram REST and Search APIs Install

Facebook Archive 2.9k Dec 30, 2022
A Python Client for News API

newsapi-python A Python client for the News API. License Provided under MIT License by Matt Lisivick. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRAN

Matt Lisivick 281 Dec 29, 2022