It’s common to send emails from your Rails app, but what about receiving incoming emails? In this tutorial, you’ll learn how to receive emails in your Rails app using Postmark’s inbound email processing.
We’ll be creating a simple blog application that allows readers to post responses to articles using email.
Let’s get started.
You’ll need a Postmark account for this tutorial. If you don’t have one already, sign up for a free developer account now.
This tutorial assumes that you’re familiar with running a Rails app locally. The demo application we’ll be using is built to run on Rails 5 using Ruby 2.4.1.
If you don’t already have Ruby 2.4.1 installed, please install it using rvm before continuing.
rvm install 2.4.1
Setting up the demo application #
Start by downloading the demo application and unzipping the contents to your home folder.
Open up Terminal and
cd into the
Install the project’s dependencies using Bundler.
gem install bundler bundle install
Now you need to set up the database. We’ll be using an SQLite database in this demo for simplicity.
Start by creating the database:
This command will set up your database and populate it with some example articles you can use for testing.
Now your database is set up, and you’re ready to run the app. Head back to the terminal and start up the Rails server.
Navigate to http://localhost:3000 in your web browser. You should see three test articles.
Configuring Postmark’s inbound processing #
Now you’ve got the demo app up and running it’s time to configure Postmark to receive your emails.
Log in to your Postmark account and create a new server that will handle your app’s inbound emails.
Head over to the Credentials tab and grab the inbound email address for this server. It should look something like
firstname.lastname@example.org. This is the email address where readers will send their article responses.
If you want to use a custom email address for inbound emails, check out the inbound domain forwarding setup guide.
config/initializers/postmark.rb file and input the hash from the start of your inbound email address. (Everything before the @ symbol.) Postmark uses this hash to determine which server inbound emails belong to.
Rails.application.config.postmark_inbound_email_hash = 'huigh8923hg782ygh7348y734g8y'
In order to test webhooks locally, you’re going to use a service called Ultrahook. Ultrahook will catch webhook payloads sent from Postmark and forward them to the Rails app running on your local machine.
If you haven’t used Ultrahook before, start by registering for an API key.
Once you’re done, add your Ultrahook API key to a
.ultrahook file in your home folder.
echo "api_key: YOUR_ULTRAHOOK_API_KEY" > ~/.ultrahook
You’re now ready to start Ultrahook.
ultrahook inbound-demo 3000
Once Ultrahook starts running, you should see a URL output in the console.
Authenticated as YOUR_USER Forwarding activated... http://inbound-demo.YOUR_USER.ultrahook.com -> http://localhost:3000
Any requests sent to
http://inbound-demo.YOUR_USER.ultrahook.com will now forward to
http://localhost:3000 on your local machine.
Now that you have Ultrahook set up, the final step of this section is to tell Postmark about your Webhook URL.
Go to the inbound settings page for your server. (Settings → Inbound)
In the Webhook field, add your ultrahook URL followed by
/responses. This path is for the endpoint that will process incoming inbound webhooks in your Rails app. (We’ll set that up shortly.)
Make sure to come back and update the Webhook URL when you’re ready to launch your application into production.
Handling inbound webhooks from Postmark #
It’s time to create the endpoint in your Rails app that will handle inbound webhooks from Postmark.
Create the controller method #
app/controllers/responses_controller.rb file in your favorite text editor.
Add a new
create method. This will receive inbound webhook payloads from Postmark that contain the responses sent from readers.
def create end
The first thing you need to do is parse the JSON payload sent by Postmark. Add the following to your new
message = JSON.parse(request.body.read)
To identify which article a response should be associated with, we’re going to add the article’s ID to the inbound email address. We’ll do this using the
Anything after the
+ will be extracted by Postmark as the
MailboxHash which is made available in the JSON request received by the Rails application.
In this example, Postmark would identify
124 as the
Processing replies to your transactional emails #
A common use case for inbound email processing is to catch replies to transactional emails. For example, if a user replies to a comment notification email for a blog post they wrote, their reply should be added to the comments section of that blog post. To process replies to your transactional emails, add a
Reply-To header on the emails your application sends out. This should be your inbound email address with a unique hash or ID which can be used to identify a database record that replies should be associated with.
Back in the
create method, retrieve the article ID from the webhook JSON.
article_id = message['MailboxHash']
Next, use this
article_id variable to find the Article that the new response should be associated with.
You can now create the new response using the data from the reader’s email.
article.responses.create( name: message['FromName'], email: message['From'], body: message['TextBody'] )
Here we’re extracting the user’s name and email address as well as the body of the email and using it to create a new Response record.
Check out the Postmark documentation for a full list of properties available in the inbound webhook JSON.
Finally, return a 200 response code so that Postmark knows the inbound email was processed successfully.
render plain: 'Response Saved', status: 200
To recap, your full
create method should now be:
def create # Parse the message message = JSON.parse(request.body.read) # Grab the Article ID from the message article_id = message['MailboxHash'] # Find the article article = Article.find(article_id) # Create a new response article.responses.create( name: message['FromName'], email: message['From'], body: message['TextBody'] # Could also use message['HtmlBody'] ) # Return a 200 code so Postmark know’s the webhook was processed render plain: 'Response Saved', status: 200 end
By default, Rails comes with a security feature that requires POST requests to include an authenticity token to validate they were made from the app. As Postmark does not have access to this authenticity token, you’ll need to disable this feature for the
Add the following above the
create method definition to disable CSRF protection on the webhook endpoint.
protect_from_forgery except: :create
Set up a route #
Now your controller action is complete you just need to register a new route for it.
Add the following to your
resources :responses, only: [:create]
Your app can now receive POST requests at
/responses which will be handled by the
create method on the
Testing inbound processing #
Your app is now ready to start processing inbound emails!
Make sure both your local Rails server and Ultrahook are still running and navigate to http://localhost:3000/articles/1.
Scroll down to the bottom of the page and hit the Send a response button. This should launch your mail client.
Note that the email address includes the
+ symbol followed by the article ID, in this case,
Type a quick message into the body of the email and hit send.
Wait a few seconds and then refresh the page. If everything is set up correctly, you should see your response at the bottom of the page.
Now navigate to a different article and post a response their too.
In this tutorial you’ve learned how to receive email in your Rails app using Postmark’s inbound email processing.
Now you’ve got the basics mastered, try tackling some more advanced topics like setting up a custom inbound email address or blocking inbound messages based on their spam score.
Be sure to let us know how you’re using inbound processing in your app.
Grab a copy of the completed code for the demo application on GitHub.
Interested in growing your audience? Write for the Postmark blog