Skip to content

Send emails with Ruby on Rails

Learn how to send transactional emails using PostStack and Ruby on Rails.

Ruby on Rails ships with ActionMailer and Net::HTTP in the standard library, so you can talk to PostStack without adding a gem. For simple transactional flows, a thin wrapper around `Net::HTTP::Post` is the smallest viable integration. For Rails-native ergonomics — previews, layouts, mailer tests — configure PostStack as the SMTP delivery method instead.

1. Install the SDK

bash
# No external gems needed — uses the standard library

2. Initialize the client

ruby
require 'net/http'
require 'json'
require 'uri'

API_KEY = ENV['POSTSTACK_API_KEY']
BASE_URL = 'https://api.poststack.dev'

3. Send an email

ruby
require 'net/http'
require 'json'
require 'uri'

api_key = ENV['POSTSTACK_API_KEY']
uri = URI('https://api.poststack.dev/emails')

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{api_key}"
request['Content-Type'] = 'application/json'
request.body = {
  from: 'hello@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Hello from Ruby!',
  html: '<h1>Welcome!</h1>'
}.to_json

response = http.request(request)
puts response.body

4. Handle errors

Ruby on Rails idioms for error handling, retries, and structured logging when calling the PostStack API.

ruby
require 'net/http'
require 'json'
require 'uri'

class PoststackError < StandardError
  attr_reader :status_code, :request_id
  def initialize(status_code, message, request_id = nil)
    super(message)
    @status_code = status_code
    @request_id = request_id
  end
end

def send_email(payload, attempts = 3)
  uri = URI('https://api.poststack.dev/emails')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.read_timeout = 10

  req = Net::HTTP::Post.new(uri)
  req['Authorization'] = "Bearer #{ENV.fetch('POSTSTACK_API_KEY')}"
  req['Content-Type'] = 'application/json'
  req.body = payload.to_json

  attempts.times do |attempt|
    res = http.request(req)
    case res.code.to_i
    when 200, 201
      return JSON.parse(res.body)
    when 429
      sleep(res['retry-after']&.to_i || (2**attempt))
    when 500..599
      sleep(2**attempt)
    else
      raise PoststackError.new(res.code.to_i, res.body, res['x-request-id'])
    end
  end
  raise 'send_email exhausted'
end

Framework integrations

ActionMailer + SMTP

In `config/environments/production.rb`, set `config.action_mailer.delivery_method = :smtp` and `smtp_settings: { address: "smtp.poststack.dev", port: 587, user_name: "poststack", password: ENV.fetch("POSTSTACK_API_KEY"), authentication: :plain, enable_starttls_auto: true }`. Every existing ActionMailer class — `UserMailer.welcome(user).deliver_later` — now goes through PostStack.

Pure Net::HTTP

For non-Rails Ruby apps (Sinatra, Hanami, Cuba, pure scripts), the example above is the entire integration. Wrap it in a service object and inject it into your routes.

Sidekiq / GoodJob workers

Push sends into a background job so the HTTP request returns quickly. The PostStack API key reads from `ENV.fetch` inside the worker — no need to pass it in job arguments.

Rails Mailer previews

Mailer previews under `test/mailers/previews` work the same way. Previews render the email but do not actually send, so you can iterate on templates without burning your sending quota.

Common pitfalls

  • Forgetting `enable_starttls_auto`

    Without STARTTLS, the SMTP submission is rejected. Always include `enable_starttls_auto: true` for port 587, or use port 465 with `tls: true`.

  • Sending from `*@gmail.com`

    Your `from` address must be on a verified PostStack domain. Sending from `example@gmail.com` is rejected. Verify your domain in the dashboard first.

  • Holding the HTTP connection open per-request

    For high-throughput, share the `Net::HTTP` instance with `http.start { ... }` so the TLS connection is reused across sends. Spinning up a new TLS handshake per send adds 100–200 ms each.

Notes

  • Uses the Ruby standard library — no gems required
  • For Rails, you can also configure PostStack as an SMTP transport in config/environments/production.rb

FAQ

Do I need to install a gem?

No. Ruby’s standard library `Net::HTTP` is enough for REST calls, and Rails’s built-in ActionMailer handles SMTP. The PostStack-specific code is tiny.

Can I use ActionMailer?

Yes — configure SMTP as shown in the integrations section. Every existing `Mailer.deliver_later` call goes through PostStack with full tracking, webhooks, and deliverability.

How do I handle rate limits?

Inspect the `Retry-After` header on a 429 response and sleep for that many seconds before retrying. The example in the error-handling section above does this.

Related guides

Ready to send emails with Ruby on Rails?

Create a free account and get your API key in under a minute.