Sending Email

Sending a single message

To send a single message, create a Message object, and pass it to send().

import pystmark

API_KEY = 'my_api_key'

# Send a single message
message = pystmark.Message(sender=SENDER, to='',
                               subject='Hi', text='A message',

pystmark.send(message, api_key=API_KEY)

You can also pass in a dictionary. It will construct the Message for you.

import pystmark

pystmark.send(dict(sender=SENDER, to='', subject='Hi',
                   text='A message', tag='greeting'), api_key=API_KEY)

Sending a single message with template

To send a single message with template, create a Message object, and pass it to send_with_template(). The template_id can be found with template meta data.

t_model = {'product_name': "Awesome Product",
           'name': "Customer Name",
           'action_url': "",
           'sender_name': "Product Team",
           'product_address_line1': "Dover",
           'product_address_line2': "DE 19012"}

message = pystmark.Message(sender=PM_SENDER, to='',

pystmark.send_with_template(message, api_key=PM_API_KEY)

Sending batched messages

This sends multiple messages in a single http request to Postmark’s batch send API. There is a hard limit of 500 messages.

If you want to send the same message but to multiple recipients, you can use send(), and construct the message with multiple to, cc or bcc addresses. See Multiple Recipients.

from pystmark import Message, send_batch

# Send multiple messages (in one batched http request)
recipients = ['you{0}'.format(i) for i in xrange(20)]
messages = [Message(sender=SENDER, to=to, subject='Hi', text='A message',
                    tag='greeting') for to in recipients]

response = send_batch(messages, api_key=API_KEY)

Multiple recipients

The Postmark API allows you to have multiple to recipients. The total number of recipients, including to, cc, and bcc is limited to 20.

from pystmark import Message, send

message = Message(sender=SENDER, subject='Hi', text='A message',
                  to=['', ''],
                  cc=['', ''],

send(message, api_key=API_KEY)

Sender Configuration

You can set defaults for your message sending using the Advanced API. For every method in the Simple API, there is a corresponding configurable sender object in the Advanced API.

from pystmark import Message, Sender

default_message = Message(sender=SENDER,
                          text='Welcome to the site',
                          html='<h1>Welcome to the site</h1>',

sender = Sender(message=default_message, api_key=API_KEY)



Attachments are allowed, up to 10MB in size. The attachment sizes are not checked to be under the limit. If you think you might go over the limit, make sure to check yourself. Only certain file extensions are allowed.

import pystmark

filename = '/tmp/example.txt'
with open(filename, 'w') as f:

message = pystmark.Message(sender='',

# Attach using filename

# Attach using binary
with open(filename) as f:
    message.attach_binary(, filename)

pystmark.send(message, api_key='the key')

Email Headers

Custom headers can be added for your email.

import pystmark

message = pystmark.Message(sender='',

message.add_header('X-my-custom-header', 'foo')

pystmark.send(message, api_key='the key')

Response Errors

Some HTTP status codes will raise a custom Exception. See Response.raise_for_status().

from pystmark import send, UnauthorizedError

r = send(dict(sender='', to='', text='hi'),
         api_key='bad key')

except UnauthorizedError:
    print 'Use your real API key'

Requests.request Arguments

If you need to pass some arguments to requests.request(), you can do so. However, you cannot modify the data keyword. It will be ignored if you give it.

from pystmark import send, Message

message = Message(sender='', to='', text='hi')

send(message, api_key='my key', **dict(headers={'X-Something': 'foo'}))

Bounce Handling

Retrieving bounced emails

Bounced emails are retrieved with get_bounces(). The request must be paginated with the count and offset. They will default to 25 and 0, respectively. If you provide a message_id (saved from the response of a previously sent message), you do not need to provide count or offset. You can filter bounces by a string match or bounce type.

from pystmark import send, get_bounces

API_KEY = 'my key'

# Get all bounces. If we do not paginate, 25 results will be returned at
# offset 0.
get_bounces(count=100, offset=0, api_key=API_KEY)

# Get bounces of a specific type
get_bounces(bounce_type='HardBounce', api_key=API_KEY)

# Get bounces filtered by email string
get_bounces(email_filter='', api_key=API_KEY)

# Get bounces for a message
r = send(dict(sender='', to='', text='hi'),
get_bounces(, api_key=API_KEY)

Retrieving a single bounce

Data for a single bounce can be retrieved given a bounce_id.

from pystmark import get_bounce, get_bounces

r = get_bounces(api_key='my key')
for bounce in r.bounces:
    get_bounce(, api_key='my key')

Retrieving the raw dump for a single bounce

The raw email dump can be retrieved with a bounce_id or with a BouncedMessage.

from pystmark import get_bounces, get_bounce_dump

r = get_bounces(api_key='my key')
for bounce in r.bounces:
    # Get dump via BouncedMessage.
    dump = bounce.dump(api_key='my key')
    # Get dump with the simple API
    dump = get_bounce_dump(, api_key='my key')

Activating a bounced message (re-sending it)

Bounces can be re-sent with activation. Keep in mind that some bounces such as hard bounces should be assumed dead.

from pystmark import get_bounces, activate_bounce

r = get_bounces(api_key='my key')
for bounce in r.bounces:

Retrieving tags for bounced messages

You can get a list of tags that have bounced messages. Tags are set on the message by you, when they are sent.

from pystmark import get_bounces, get_bounce_tags

r = get_bounces(api_key='my key')
for bounce in r.bounces:

Retrieving delivery statistics

Delivery stats summarize your bounces.

from pystmark import get_delivery_stats

r = get_delivery_stats(api_key='my key')
print 'Inactive Messages:', r.inactive
print 'Total bounces:',
print 'Bounces:'
for bounce in r.bounces.values():
    print '\tType:', bounce.type
    print '\t\tName:',
    print '\t\tCount:', bounce.count