Postmark

This add-on is operated by Postmark

Email delivery for web apps

Postmark

Last Updated: 11 February 2014

Table of Contents

Postmark add-on removes the headaches of delivering and parsing transactional email for your web app, with minimal setup time and zero maintenance. We have years of experience getting email to the inbox, so you can focus on what you do best.

Use our Send API or our simple SMTP interface to start sending in minutes. Our Inbound API parses incoming email and forwards it to you via a web hook, making it easy to handle incoming email in your application.

Provisioning the add-on

Postmark can be attached to a Heroku application via the CLI:

A list of all plans available can be found on the Postmark add-on page.

$ heroku addons:add postmark:10k
-----> Adding postmark to sharp-mountain-4005... done, v18 (free)

Once Postmark has been added a POSTMARK_API_KEY setting will be available in the app configuration and will contain the api key to access Postmark API or SMTP interface. This can be confirmed using the heroku config:get command.

$ heroku config:get POSTMARK_API_KEY
22874e6c-32f8-4e30-a0ee-45e1ed144a6b

After installing the Postmark add-on you also need to create at least one sender signature and configure your application to fully integrate with the add-on.

Creating sender signatures

Sender signatures are required in order to verify that, well, you really own the mailbox, and that you are not a spammer (yes, we hate spam too). You must have a sender signature for each from address used in your application.

To create a sender signature, open the Postmark Dashboard from the terminal:

$ heroku addons:open postmark
Opening postmark for sharp-mountain-4005…

You can also proceed to the Postmark Dashboard from your application page on the Heroku web site.

Setting up a local development environment

Postmark automatically sets environment variables on your Heroku servers, but sometimes you may need to recreate the environment locally. Foreman aims to solve this for you. You can save the environment variables in your .env file and let Foreman do the rest.

  $ bash -c 'echo "POSTMARK_API_KEY=`heroku config:get POSTMARK_API_KEY`" >> .env'
  $ bash -c 'echo "POSTMARK_SMTP_SERVER=`heroku config:get POSTMARK_SMTP_SERVER`" >> .env'
  $ bash -c 'echo "POSTMARK_INBOUND_ADDRESS=`heroku config:get POSTMARK_INBOUND_ADDRESS`" >> .env'

Sending emails via the Postmark SMTP interface

You want to try Postmark, but your application uses SMTP to send email? You can instantly switch your current email delivery without having to modify the application. This feature lets you use plain SMTP to send your messages and, to use it, you need to only change your configuration to point to the Postmark SMTP server.

The SMTP listener endpoint is available at smtp.postmarkapp.com on port 25 and 2525 (to get around firewall issues). We support both plain text authentication and CRAM-MD5. We recommend the latter as it is a lot more secure. CRAM-MD5 encrypts just the authentication process, but the message content is still sent as plain text. You can encrypt the entire connection using TLS via the standard STARTTLS SMTP extension. STARTTLS is supported by the vast majority of mailers and some of them, like Ruby’s ActionMailer automatically switch to encrypted communication when they detect that the server supports it.

Here is a sample configuration for Ruby Mail library:

Mail.defaults do
  delivery_method :smtp, {
    :address => ENV['POSTMARK_SMTP_SERVER'],
    :port => '25',
    :domain => 'yourapp.heroku.com',
    :user_name => ENV['POSTMARK_API_KEY'],
    :password => ENV['POSTMARK_API_KEY'],
    :authentication => :plain,
    :enable_starttls_auto => true
  }
end

And Rails/ActionMailer:

ActionMailer::Base.smtp_settings = {
  :port           => '25',
  :address        => ENV['POSTMARK_SMTP_SERVER'],
  :user_name      => ENV['POSTMARK_API_KEY'],
  :password       => ENV['POSTMARK_API_KEY'],
  :domain         => 'yourapp.heroku.com',
  :authentication => :plain,
}
ActionMailer::Base.delivery_method = :smtp

Sending emails in Ruby

We support the official Ruby gem called postmark. It’s integrated with the Ruby Mail library and requires it to be installed. You can install both manually using the following command:

$ gem install mail postmark

If your application is using Bundler, add the following entries to your Gemfile and update application dependencies with bundle install:

gem 'mail'
gem 'postmark'

The following example will use the gem to send a text email with attachments:

message = Mail.new do
  from            'leonard@bigbangtheory.com'
  to              'Dr. Sheldon Cooper <sheldon@bigbangtheory.com>'
  subject         'Have you seen these pictures of yours?'
  body            'You look like a geek!'
  add_file        '1.jpeg'

  delivery_method Mail::Postmark, :api_key => ENV['POSTMARK_API_KEY']
end

message.attachments['sheldon.jpeg'] = File.read('2.jpeg')

message.deliver
# => #<Mail::Message:70185826686240, Multipart: true, Headers: <From: leonard@bigbangtheory.com>, <To: sheldon@bigbangtheory.com>, <Message-ID: ba644cc1-b5b1-4bcb-aaf8-2f290b5aad80>, <Subject: Have you seen these pictures of yours?>, <Content-Type: multipart/mixed; boundary=--==_mimepart_5121f9f1ec653_12c53fd569035ad817726>>

Sending emails in Ruby on Rails 3.x

Our postmark-rails Ruby gem was designed to make switching to the Postmark API as easy as possible. Ruby on Rails applications will need to add the following entry into their Gemfile specifying the Postmark client library.

gem 'postmark-rails'

Update application dependencies with bundler.

$ bundle install

Add this to your config/application.rb:

config.action_mailer.delivery_method   = :postmark
config.action_mailer.postmark_settings = { :api_key => ENV['POSTMARK_API_KEY'] }

That’s it. Now send emails as usual.

class TestMailer < ActionMailer::Base

  def tagged_message
    mail(
      :subject => 'Did you know Postmark has a Heroku add-on?',
      :to      => 'sheldon@bigbangtheory.com',
      :from    => 'leonard@bigbangtheory.com',
      :tag     => 'my-tag'
    )
  end

end

Sending emails in Ruby on Rails 2.x

Rails 2.x applications will need to add the following to config/environment.rb:

Rails::Initializer.run do |config|

  # ...

  config.gem 'postmark-rails'
  require    'postmark-rails'

  config.action_mailer.postmark_api_key = ENV['POSTMARK_API_KEY']
  config.action_mailer.delivery_method  = :postmark

  # ...

end

Usage example:

class SuperMailer < ActionMailer::Base

  def email
    from       "leonard@bigbangtheory.com"
    subject    "Hello from Postmark"
    recipients "sheldon@bigbangtheory.com"
    tag        "big-bang"
  end

end

See the postmark-rails gem documentation for more examples.

Sending emails in Python

Python users will need to install the python-postmark library. It’s possible to install the library from PyPy:

$ pip install python-postmark

The following example will use the python-postmark library to send a tagged email.

import os
from postmark import PMMail

message = PMMail(api_key = os.environ.get('POSTMARK_API_KEY'),
                 subject = "Hello from Postmark",
                 sender = "leonard@bigbangtheory.com",
                 to = "sheldon@bigbangtheory.com",
                 text_body = "Hello",
                 tag = "hello")

message.send()

Check out the PMMail class’ documentation for more information on usage.

Sending emails in NodeJS

NodeJS users can use the postmark package available to install using NPM:

$ npm install postmark

The following example will use the postmark package for NodeJS to send a tagged text email:

var postmark = require("postmark")(process.env.POSTMARK_API_KEY)

postmark.send({
    "From": "leonard@bigbangtheory.com",
    "To": "sheldon@bigbangtheory.com",
    "Subject": "Hello from Postmark",
    "TextBody": "Hello!",
    "Tag": "big-bang"
}, function(error, success) {
    if(error) {
        console.error("Unable to send via postmark: " + error.message);
       return;
    }
    console.info("Sent to postmark for delivery")
});

Sending emails in Clojure

Clojure users can use clojure-postmark to interact with the API. To get started add the following entry to your project dependencies (we assume you’re using Leiningen):

[postmark "1.1.0"]

The following example will use the clojure-postmark library to send a tagged text email:

(use '[postmark.core :only (postmark)])

(def api-key (get (System/getenv) "POSTMARK_API_KEY"))

(def send-message (postmark api-key "leonard@bigbangtheory.com"))

(send-message {:to "sheldon@bigbangtheory.com"
               :subject "Hello from Postmark"
               :text "Hello!"
               :tag "big-bang"})

Using Postmark Inbound

Postmark makes email parsing easy, too. We provide you with a unique inbound email address, which can be used for receiving emails. Postmark then parses the incoming emails and sends you the data in a nicely formatted JSON document via web hook. To see it, run:

$ heroku config:get POSTMARK_INBOUND_ADDRESS
3e5317xxxx48ce3bxxxx1a7be74f665f@inbound.postmarkapp.com

Depending on your use, you may not want your users to see the @inbound.postmarkapp.com email. There are two options: MX Record Forwarding (beta) and custom forwarding with Gmail/Google Apps.

Our MX Record Support is in beta until we’ve released a web-based configuration UI. It’s currently API-only, and you can read the documentation on configuring MX Records.

If you’d like to wait until the feature is included in Postmark’s UI, or if you do not have access to edit your DNS records, you can read our help article to learn how to configure a custom forwarding email address from your Gmail/Google Apps account.

In order for your application receive the emails that we parse, you will need to tell Postmark where to send the JSON data for each inbound email it processes, which is done via an HTTP POST to a URL of your choice. You can set this URL in the Settings page for your Postmark server on the Postmark Dashboard.

To test your inbound server, we recommend using RequestBin first.

Here is a simple Ruby/Sinatra application that does basic inbound processing:

require 'sinatra'
require 'json'
require 'logger'

logger = Logger.new(STDOUT)

class Comment
  attr_accessor :attributes

  def self.create_from_inbound_hook(message)
    self.new(:text => message["TextBody"],
             :user_email => message["From"],
             :discussion_id => message["MailboxHash"])
  end

  def initialize(attributes={})
    @attributes = attributes
  end
end

post '/inbound' do
  request.body.rewind
  comment = Comment.create_from_inbound_hook(JSON.parse(request.body.read))
  logger.info comment.inspect
end

Let’s assume the inbound hook is set to http://myapp.heroku.com/inbound. Then, if a user sends an email to 3e5317xxxx48ce3bxxxx1a7be74f665f+discussion7864@inbound.postmarkapp.com (the part after plus sign is called “mailbox hash” and can be used to transfer additional information), it will be processed by Postmark and forwarded to the app’s inbound hook as a JSON object. The example app creates a new instance of Comment object using JSON object provided by Postmark.

I, [2013-02-28T05:18:56.407910 #2]  INFO -- : #<Comment:0x00000002979260 @attributes={:text=>"That's what you said about the Green Lantern movie. You were 114 minutes of wrong. ", :user_email=>"sheldon@bigbangtheory.com", :discussion_id=>"discussion7864"}>

Migrating between plans

Application owners should carefully manage the migration timing to ensure proper application function during the migration process.

Use the heroku addons:upgrade command to migrate to a new plan.

$ heroku addons:upgrade postmark:gold
-----> Upgrading postmark:newplan to sharp-mountain-4005... done, v18 ($49/mo)
       Your plan has been updated to: postmark:gold

Removing the add-on

Postmark can be removed via the CLI.

This will destroy all associated data and cannot be undone!

$ heroku addons:remove postmark
-----> Removing postmark from sharp-mountain-4005... done, v20 (free)

Support

If you need help or have questions, you can contact Postmark at any time at support@postmarkapp.com or @postmarkapp on Twitter. For system status, visit http://status.postmarkapp.com.