Skip to content
NewA free test that shows whether your emails will reach the inbox.
Quickstart run with Ruby 4.0.7, 5 min read

Send email from Ruby with the Runearc SDK

A gem that uses only the standard library, in any framework. This page installs it, sends an email to a test inbox, reads it back and verifies a signed webhook, with the output of a real run.

Terminal
gem install runearc

Not published yet: this is the command that will work after the release. See the SDK page for the status of every package.

Terminal output of the Ruby quickstart: an inbox address, the id of the email sent, the received subject, and webhook verified
The Ruby quickstart, run once with ruby quickstart.rb: it creates an inbox, sends an email to it, reads it back and verifies a signed webhook. Output unedited.

Install

Ruby 3.0 or later. The gem uses only the standard library, and it works in any framework. The commands on this page are the ones that will work once the package is released; none of the five Runearc SDK packages is on a registry yet, and until then the Resend SDK or plain HTTP calls with your API key do the same work. The SDK covers emails, senders, inboxes, messages, threads, conversations, domains, webhooks, keys, suppressions and events. Contacts, lists, campaigns, sequences, templates, forms, pages and analytics are not in it: use the REST API, the CLI or MCP for those.

Terminal
gem install runearc

Create an API key in the dashboard and export it as RUNEARC_API_KEY. The quickstart below also reads RUNEARC_FROM, a sender address on a domain you have verified, and RUNEARC_BASE_URL to point at another API host. Tested on Ruby 4.0.7.

Send an email

The whole quickstart: create an inbox, send an email to it, wait for it to arrive and check a webhook signature.

# frozen_string_literal: true

require "json"
require "openssl"
require "securerandom"
require "runearc"

runearc = Runearc::Client.new # reads RUNEARC_API_KEY and RUNEARC_BASE_URL

inbox = runearc.inboxes.create(display_name: "quickstart")
puts "inbox #{inbox[:address]}"

subject = "Hello from the Ruby SDK #{SecureRandom.hex(3)}"
sent = runearc.emails.deliver(from: ENV.fetch("RUNEARC_FROM"), to: inbox[:address], subject: subject, text: "It works.")
puts "sent #{sent[:id]}"

waited = runearc.messages.wait(inbox[:id], subject: subject, after: inbox[:created_at], timeout: 30)
abort "no message arrived within 30 seconds" unless waited
puts "received #{waited[:message][:subject]}"

# Sign a sample event the way Runearc does (Standard Webhooks), then verify it.
key = SecureRandom.random_bytes(32)
secret = "whsec_#{[key].pack("m0")}"
payload = JSON.generate(id: "evt_1", type: "message.delivered", data: { email_id: sent[:id] })
timestamp = Time.now.to_i.to_s
signature = [OpenSSL::HMAC.digest("SHA256", key, "evt_1.#{timestamp}.#{payload}")].pack("m0")
headers = { "webhook-id" => "evt_1", "webhook-timestamp" => timestamp, "webhook-signature" => "v1,#{signature}" }
Runearc::Webhook.verify(payload: payload, headers: headers, secret: secret)
puts "webhook verified"

runearc.inboxes.delete(inbox[:id])

emails.deliver takes the same fields as the REST API and returns a Hash with symbol keys, including the new email's id. It sends an Idempotency-Key for you, so a retry does not send twice. Passing after: inbox[:created_at] to wait is needed because wait only matches messages received after it starts, and the email can arrive before the wait begins.

Terminal output of the Ruby quickstart: an inbox address, the id of the email sent, the received subject, and webhook verified
The Ruby quickstart, run once with ruby quickstart.rb: it creates an inbox, sends an email to it, reads it back and verifies a signed webhook. Output unedited.

The same output as selectable text

inbox inbox-a9h3nb@5exuc9.runearc.email
sent eml_01m70nxwhjj3p9maya98n1ksrs
received Hello from the Ruby SDK f7cec2
webhook verified

Ids and the inbox address are from that one run, on November 9, 2026.

Read an inbox

messages.wait blocks for up to timeout seconds and returns nil when nothing arrived, so check for it. When a message matches, it comes back with the one time codes and links already extracted, which is what a sign-up test needs. The screenshot shows the same inbox in the dashboard. See wait for an email for every filter.

waited = runearc.messages.wait(inbox[:id], subject: subject, after: inbox[:created_at], timeout: 30)
abort "no message arrived within 30 seconds" unless waited
puts "received #{waited[:message][:subject]}"
# waited[:codes] and waited[:links] hold the one time codes and links found in the message
Runearc dashboard showing the email sent by the Ruby quickstart, open in the test inbox
The email that ruby quickstart.rb sent, as it appears in the Runearc dashboard. Local stack, throwaway workspace and test addresses only.

Verify a webhook

The lines in the quickstart verify a sample event the script signs itself with a random secret. It is not a live delivery from Runearc; it shows that Runearc::Webhook.verify accepts a correctly signed body and checks the timestamp, which must be within five minutes. For a real delivery, pass the raw request body and the headers (a Rack env works), as in the receiver tab.

headers = { "webhook-id" => "evt_1", "webhook-timestamp" => timestamp, "webhook-signature" => "v1,#{signature}" }
Runearc::Webhook.verify(payload: payload, headers: headers, secret: secret)
puts "webhook verified"

The first tab is from the quickstart we ran. The receiver is from the package README and was not part of that run. The signature headers and the secret format are on the webhooks page.

Errors and retries

Methods return the parsed response and raise a Runearc::Error. It carries status, a stable code to branch on, a kind such as forbidden, a message, and a fix when there is something to do. Narrower classes such as RateLimitError and ConnectionError let you rescue one case.

begin
  runearc.emails.deliver(from: "noreply@acme.com", to: "bob@example.com", subject: "Hi", text: "Hi")
rescue Runearc::Error => e
  e.status # => 403
  e.code   # => "sender_not_verified", a stable string to branch on
  e.fix    # what to do about it, when there is something to do
  raise
end

# A stable key makes your own retries safe too, for example from a job queue.
runearc.emails.deliver(idempotency_key: "welcome/#{user.id}", **email)

A request is retried up to two times by default, with exponential backoff and jitter, and the wait honours Retry-After. A 429 is always retried; a 5xx, a network error or a timeout is retried only when repeating the request is safe. Other 4xx errors are never retried, and creating an inbox is not repeated after a 5xx. Mail sending gets an Idempotency-Key automatically and every retry reuses it; Runearc remembers keys for 24 hours.

This code is from the package README, not from the quickstart run. Every error code and its fix is listed on the errors page.

Where other SDKs are better

Read on November 9, 2026. Runearc's SDK is new and covers eleven resources; the others have longer histories and, in several cases, more features. We list them in alphabetical order.

  • Amazon SES

    SES covers Ruby through the AWS SDK for Ruby. The page we read was tested on Ruby 1.9.3, so it is dated.

  • Mailgun

    Mailgun lists a Ruby SDK among its SDKs for Go, Node.js, PHP, Java and Python.

  • Postmark

    Postmark lists an official Ruby library that Postmark maintains itself.

  • Resend

    Resend's Ruby gem has docs with examples for attachments, templates, scheduling, audiences, domains and inbound webhooks, which are outside Runearc's eleven resources.

  • SendGrid

    SendGrid's Ruby quickstart is a long-established path: it shows installed gem versions and the 202 status, and has a troubleshooting section.

Maturity and deliverability track record are where Runearc is behind: the providers above have sent email for longer than we have. For the same comparison across the whole product, see Runearc compared with Resend.

Questions

Is the gem on RubyGems yet?

Not yet. The gem is written and tested, and gem install runearc is the command that will work after the release. Until then, Net::HTTP with your API key does the same work.

Which Ruby version does it need?

Ruby 3.0 or later. It uses only net/http, json and openssl from the standard library. We ran the quickstart on Ruby 4.0.7.

Is it an ActionMailer delivery method?

No. It is an API client, not a delivery method for a framework mailer, and it is plain Ruby with no framework code. We ran the quickstart as a plain script.

Is the webhook line in the quickstart a real delivery?

No. The script signs a sample event with a random secret, the way Runearc signs deliveries, and then verifies it. It shows that verification works; it does not show a delivery from Runearc.

Does the SDK cover contacts, campaigns or sequences?

No. It covers emails, senders, inboxes, messages, threads, conversations, domains, webhooks, keys, suppressions and events. Everything else is in the REST API, the CLI and MCP.

Put Runearc to work

Get inboxes, sending, your own domains and MCP in one workspace. The free plan includes 3 inboxes, 3,000 emails a month and 3 custom domains, with no card.