14
.
11
.
2023
25
.
02
.
2021
Ruby on Rails
Tutorial

How To Receive Emails With a Rails App in 2021

Michał Łęcicki
Ruby Developer

Table of content:

  1. Problem
  2. Solution 0: Rails Action Mailbox
  3. Solution 1: Third-party integration with Griddler
  4. Solution 2: IMAP protocol
  5. Solution 3: AWS SES
  6. Summary

Problem

Some time ago, we needed to implement a full email inbox feature in the Ruby on Rails application. It was supposed to have all the basic functionalities that regular email inboxes have: send and receive messages, collect them in threads, have a contact book, etc. While email sending is a relatively frequent feature among Rails applications (there are tons of different solutions around the web), receiving messages is not so popular. So, let’s take a look at possible ways of building an email receiver mechanism with Rails.

mailphoto

Solution 0: Rails Action Mailbox

Rails 6 release in 2019 changed the way of handling emails in Ruby on Rails applications by introducing the Action Mailbox feature. It allowed routing incoming emails to controller-like mailboxes - for every new email, there now was an InboundEmail record created that could be processed later on. Action Mailbox by default uses Active Storage to keep messages in the cloud and automatically provides a background job for deleting old emails. Moreover, it integrates easily with the most popular transactional email services like Mailgun, SendGrid, Mandrill, Postmark, and allows to handle emails directly with Postfix, Exim, or Qmail. The only disadvantage: using Action Mailbox requires Rails 6, which can be hard to achieve if you are maintaining old applications with legacy code.

To sum up: use Action Mailbox if you can, otherwise keep reading to see other solutions!

Solution 1: Third-party integration with Griddler

This was the most common solution before Rails 6. Basically, developers built a similar mechanism to what Action Mailbox provides but using a ruby gem called Griddler. It adds an endpoint for receiving messages and lets the developer define a class that will be responsible for processing messages later on (like creating a database entry with an email body or sending an automatic reply). It’s also possible to easily integrate Griddler with transactional email services like Sendgrid or Mailgun (there are even dedicated gem versions, like griddler-sendgrid or griddler-mandrill). Disadvantages? It’s a little outdated. According to The Ruby Toolbox page, it has a low commit activity in the last 3 years and no release in over a year.

To sum up: a little outdated, but still a usable alternative for Action Mailbox.

Solution 2: IMAP protocol

IMAP (Internet Message Access Protocol) was created in 2003. Its goal was to define how email communication across all the web should work. So why don’t use it directly? Without a doubt, the most popular is a ruby built-in library Net::IMAP. It allows all basic operations provided by the aforementioned protocol, like connecting to the IMAP server, getting a list of inboxes, fetching email messages, etc. Unfortunately, using it is a bit troublesome: protocol itself is a little enigmatic, Net::IMAP library documentation could be more precise and, most importantly, it doesn’t provide some features of modern email inboxes, like handling attachments or connecting via SSL (or requires a significant amount of work to add them). Building a complex solution based on Net::IMAP library requires much work and should be considered only when other solutions are not viable (or as an interesting side project).

To sum up: Net::IMAP is for very simple use cases or for radical geeks who want to implement everything on their own.

Solution 3: AWS SES

Amazon Simple Email Service allows cost-effective handling of emails: both incoming and outgoing. It integrates very well with other AWS services (eg. S3, Lambda) and provides lots of flexibility in terms of architecture design. Building an AWS SES-based email processor with Rails application could be more complex than the options mentioned above and will require some knowledge about AWS infrastructure, but will also allow creating a well-tailored solution. This was the path my team chose when implementing an email receiver (after creating a prototype and confirming that it meets all requirements). We integrated AWS SES with S3 for storing all incoming messages and with Lambda function, which is invoked every time a new message comes. Then, Lambda saves information about new emails to the database which is used by the Rails application. In the end, the whole architecture is very flexible and extendable - I will present its details in the next blog post. :)

To sum up: AWS SES is the best solution for more complex systems, which already use AWS infrastructure.

Summary

There are many different options to implement email receiving in Ruby on Rails applications. Probably the easiest and most straightforward one is picking Action Mailbox, but it might be not possible for applications with older versions of Rails. In such cases, one should consider other circumstances, such as architecture dependencies, specific feature requirements, or even budget to choose the most suitable solution.

Michał Łęcicki
Ruby Developer

Check my Twitter

Check my Linkedin

Did you like it? 

Sign up To VIsuality newsletter

READ ALSO

Writing Chrome Extensions Is (probably) Easier Than You Think

14
.
11
.
2023
Antoni Smoliński
Tutorial
Frontend
Backend

Bounded Context - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

The origin of Poltrax development - story of POLTRAX (part 2)

29
.
11
.
2023
Stanisław Zawadzki
Ruby on Rails
Startups
Business
Backend

Ruby Meetups in 2022 - Summary

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Visuality
Conferences

Repository - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Example Application - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

How to launch a successful startup - story of POLTRAX (part 1)

14
.
11
.
2023
Michał Piórkowski
Ruby on Rails
Startups
Business

How to use different git emails for different projects

14
.
11
.
2023
Michał Łęcicki
Backend
Tutorial

Aggregate - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Visuality at wroc_love.rb 2022: It's back and it's good!

14
.
11
.
2023
Patryk Ptasiński
Ruby on Rails
Conferences
Ruby

Our journey to Event Storming

14
.
11
.
2023
Michał Łęcicki
Visuality
Event Storming

Should I use Active Record Callbacks?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Tutorial

How to rescue a transaction to roll back changes?

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Backend
Ruby
Tutorial

Safe navigation operator '&.' vs '.try' in Rails

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Ruby
Tutorial

What does the ||= operator actually mean in Ruby?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Ruby
Tutorial

How to design an entity - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Entity - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial

Should I use instance variables in Rails views?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Frontend
Backend
Tutorial

Data Quality in Ruby on Rails

14
.
11
.
2023
Michał Łęcicki
Ruby on Rails
Backend
Software

We started using Event Storming. Here’s why!

14
.
11
.
2023
Mariusz Kozieł
Event Storming
Visuality

First Miłośnicy Ruby Warsaw Meetup

14
.
11
.
2023
Michał Łęcicki
Conferences
Visuality

Should I use Action Filters?

14
.
11
.
2023
Mateusz Woźniczka
Ruby on Rails
Backend
Tutorial

Value Object - DDD in Ruby on Rails

17
.
03
.
2024
Paweł Strzałkowski
Ruby on Rails
Domain-Driven Design
Backend
Tutorial