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
# No external gems needed — uses the standard library2. Initialize the client
require 'net/http'
require 'json'
require 'uri'
API_KEY = ENV['POSTSTACK_API_KEY']
BASE_URL = 'https://api.poststack.dev'3. Send an email
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.body4. Handle errors
Ruby on Rails idioms for error handling, retries, and structured logging when calling the PostStack API.
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'
endFramework 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.