DEV Community

Rails Designer
Rails Designer

Posted on • Originally published at railsdesigner.com on

Inbound email in Rails apps with Fuik

Fuik is a Rails engine for handling webhooks that I launched recently. But it can also be used to process inbound emails! 💡

When working with inbound email in Rails using Action Mailbox, there’s a key requirement: managing EML files and blob storage. Once an email arrives at your domain, your email provider captures it and sends the data to you via webhook. You then extract what you need and process (or store) it. Action Mailbox requires: ActiveStorage ánd ActionMailer.

But what if you don’t have a need for ActiveStorage (including its cloud storage setup) or ActionMailer (because you use Courrier).

Most transactional email providers send their inbound emails as webhooks: Postmark, SendGrid, Mailgun and Mailpace. They all POST the email data to a webhook URL you configure.

Fuik is great at capturing just that: it captures those incoming webhooks, stores them in the database and calls your event class to process them. You see all your webhooks in at /webhooks. You can inspect and copy payloads, pull path accessors and generally debug what’s happening.

It is simple to get started:

bundle add fuik
bin/rails generate fuik:install
bin/rails db:migrate

Enter fullscreen mode Exit fullscreen mode

That’s it. Your app now has /webhooks endpoints ready to receive any webhooks. Now to process inbound emails, let’s look at Postmark as an example (though every provider that sends inbound emails as webhooks wil work).

Postmark lets you receive inbound emails by pointing a MX record to their servers and then configure a webhook URL. When an email arrives, the data is POSTed to you. Let’s see how to process it in your app with Fuik.

Generate the class:

bin/rails generate fuik:provider postmark inbound_email

Enter fullscreen mode Exit fullscreen mode

This creates three files.

Now open app/webhooks/postmark/inbound_email.rb. Postmark sends "To", "From", "Subject", "TextBody", and "HtmlBody". Route emails based on the recipient address:

module Postmark
  class InboundEmail < Base
    def process!
      return if to_email.blank?

      case to_email
      when /replies-.*@/
        message = Message.find_by(email_address: to_email)
        message.replies.create!(
          content: text_content,
          from: from_email
        )
      when /support@/
        SupportTicket.create!(
          from: from_email,
          subject: subject,
          body: text_content
        )
      end

      @webhook_event.processed!
    end

    private

    def to_email = payload["To"]

    def from_email = payload["From"]

    def subject = payload["Subject"]

    def text_content = payload["TextBody"]
  end
end

Enter fullscreen mode Exit fullscreen mode

Postmark doesn’t send an event type in the payload (all inbound webhooks are inbound emails), so you set it statically. Use Fuik’s config (app/webhooks/postmark/config.yml) to extract it:

event_type:
  source: static
  value: inbound_email

Enter fullscreen mode Exit fullscreen mode

Point your Postmark inbound webhook to https://yourdomain.com/webhooks/postmark in their dashboard, and emails start flowing in.

In the repo shared, I also added an example for Sendgrid to show another example how to do this.

Any provider with webhooks

Postmark and SendGrid are just examples. Mailgun, Brevo, Mailpace and others all send structured JSON via webhooks. The pattern is the same. Generate a provider, map the payload fields to your private methods, add your business logic and mark the event as processed.

Check out the example repository with both Postmark and SendGrid set up.

Top comments (0)