New from emailrHealthCheck Email iconHealthCheck Email
emailr_

Send email from Rails with emailr_

Send Action Mailer email from Rails through the emailr_ API with a custom delivery method, deliver_later support and signed webhook verification.

Rails iconRailsFramework

Rails apps already describe email with Action Mailer. Instead of rewriting mailers, register a small custom delivery method that hands each rendered message to the emailr_ API. deliver_now and deliver_later keep working.

There's no Ruby gem yet, so the delivery method calls POST https://api.emailr.dev/v1/emails/send with Net::HTTP from the standard library.

Set up emailr_ with Rails

  1. 01

    Create an API key

    Create a key under API keys in the dashboard. Keys start with et_live_ and are scoped to one domain workspace. Store it as EMAILR_API_KEY in your secret manager or environment, never in client-side code.

  2. 02

    Add and verify your sending domain

    In the dashboard, open Domains and add the domain you send from. A subdomain such as mail.yourcompany.com keeps transactional reputation separate from your corporate mailbox.

    Emailr generates the DNS records: a DKIM TXT record on the emailr._domainkey selector, an SPF TXT record, and an MX + TXT pair on the send subdomain used as the MAIL FROM / Return-Path. A DMARC record is optional but recommended.

    Emailr's DKIM selector and send subdomain don't collide with other providers' records, so you can add them before cutting over and send from both providers during the migration. A domain can only have one SPF record: if one already exists, merge Emailr's include: into it instead of adding a second record.

  3. 03

    Store the key

    Put EMAILR_API_KEY and EMAILR_WEBHOOK_SECRET in your environment or Rails credentials.

  4. 04

    Add a delivery method

    Action Mailer calls deliver! with a rendered Mail::Message. Pull out the HTML and text parts and post them as JSON. Raising on a non-2xx response lets Active Job retry deliver_later jobs.

    lib/emailr_delivery.rbruby
    require "net/http"
    require "json"
    
    class EmailrDelivery
      ENDPOINT = URI("https://api.emailr.dev/v1/emails/send")
    
      def initialize(settings)
        @api_key = settings.fetch(:api_key)
      end
    
      def deliver!(mail)
        html = mail.html_part&.decoded || (mail.mime_type == "text/html" ? mail.decoded : nil)
        text = mail.text_part&.decoded || (mail.mime_type == "text/plain" ? mail.decoded : nil)
    
        payload = {
          from: mail[:from].value,
          to: mail.to,
          cc: mail.cc,
          bcc: mail.bcc,
          subject: mail.subject,
          html: html,
          text: text,
          reply_to_email: mail.reply_to&.first,
        }.compact
    
        response = Net::HTTP.post(
          ENDPOINT,
          payload.to_json,
          "Authorization" => "Bearer #{@api_key}",
          "Content-Type" => "application/json",
        )
        raise "Emailr error #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
      end
    end
  5. 05

    Register it

    Register the method in an initializer and select it for the environments that should send real email.

    config/initializers/emailr.rbruby
    require Rails.root.join("lib/emailr_delivery")
    
    ActionMailer::Base.add_delivery_method :emailr, EmailrDelivery,
      api_key: ENV.fetch("EMAILR_API_KEY", nil)
    
    # config/environments/production.rb
    # config.action_mailer.delivery_method = :emailr
  6. 06

    Verify delivery webhooks

    Use request.raw_post for the HMAC and skip CSRF protection for this controller only.

    app/controllers/emailr_webhooks_controller.rbruby
    class EmailrWebhooksController < ActionController::API
      def create
        payload = request.raw_post
        expected = OpenSSL::HMAC.hexdigest("SHA256", ENV.fetch("EMAILR_WEBHOOK_SECRET"), payload)
        signature = request.headers["X-Emailr-Signature"].to_s
    
        unless ActiveSupport::SecurityUtils.secure_compare(expected, signature)
          return head :unauthorized
        end
    
        event = JSON.parse(payload)
        # event["event"] is e.g. "email.bounced"; details are in event["data"]
        head :ok
      end
    end
    
    # config/routes.rb
    # post "/webhooks/emailr", to: "emailr_webhooks#create"

Tips

  • Inheriting from ActionController::API skips CSRF checks; if you inherit from ApplicationController, add skip_forgery_protection.
  • Attachments added with attachments[...] aren't forwarded by this minimal delivery method. Add them as { filename:, content: Base64.strict_encode64(...), contentType: } if you need them.
  • Keep the :test delivery method in your test environment so specs never call the API.

Frequently asked questions

Can I keep using Action Mailer with emailr_?

Yes. A custom delivery method sends each rendered mailer through the emailr_ API, so your mailers, views and deliver_later calls stay the same.

Is there a Ruby gem for emailr_?

Not yet. The REST API is small enough to call with Net::HTTP, as shown in this guide.

Does deliver_later retry failed sends?

Yes, if the delivery method raises. Active Job retries according to your queue adapter's settings.

How do I verify emailr_ webhooks in Rails?

Compute OpenSSL::HMAC.hexdigest('SHA256', secret, request.raw_post) and compare it to the X-Emailr-Signature header with ActiveSupport::SecurityUtils.secure_compare.

Start sending in minutes

Create a free account, verify your domain and send your first email. No credit card required.