Email Fast Get a sandbox key
Guides

Send email with Rails

A service object plus an ActiveJob — reads like a mailer, retries like a job.

Facts verified 2026-07-17 — corrections: hello@emailfast.dev

Replace the mailer, keep the shape: a small service object owns the HTTP call, an ActiveJob owns the retry semantics, and WelcomeEmailJob.perform_later(user) reads exactly like deliver_later did. Subject, recipient, and variables travel as plain arguments; the HTML template lives with Email Fast, not in app/views.

# app/services/email_fast.rb — stdlib Net::HTTP, no gem
require "json"
require "net/http"

class EmailFast
  ENDPOINT = URI("https://api.emailfast.dev/v1/emails")

  def self.send_email(to:, subject:, html:, data: {}, idempotency_key:)
    req = Net::HTTP::Post.new(ENDPOINT)
    req["Authorization"] = "Bearer #{Rails.application.credentials.emailfast_api_key}"
    req["Content-Type"] = "application/json"
    req.body = { to:, subject:, html:, data:, idempotency_key: }.to_json

    res = Net::HTTP.start(ENDPOINT.host, ENDPOINT.port, use_ssl: true, read_timeout: 10) do |http|
      http.request(req)
    end
    raise "Send rejected (#{res.code}): #{res.body}" unless res.is_a?(Net::HTTPSuccess)

    JSON.parse(res.body)
  end
end
# app/jobs/welcome_email_job.rb — where a mailer used to be
class WelcomeEmailJob < ApplicationJob
  queue_as :default

  def perform(user)
    EmailFast.send_email(
      to: user.email,
      subject: "Welcome aboard",
      html: "<p>Hi {{name}}, your account is ready.</p>",
      data: { name: user.name },
      idempotency_key: "welcome-#{user.id}" # a retried job replays, never re-sends
    )
  end
end

# wherever you called UserMailer.welcome(user).deliver_later:
WelcomeEmailJob.perform_later(user)

a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.

Gotchas

Next

See it for yourself

Sandbox keys run the real pipeline dry — real validation, real events, a hosted inbox, no email sent. Early access is onboarding now.