Guide
How to send email with Ruby on Rails
Send email from Rails with Net::HTTP and the REST API.
In short
Create a Sendpository account, verify your domain, put your API key inSENDPOSITORY_API_KEY, and send with the code below - one HTTPS request per email, from server-side code only.1. Verify your sending domain
Add your domain in the dashboard and publish the three DNS records it shows - SPF and a bounce record on an sp. subdomain, and a DKIM key on your apex. Your existing records are never edited. Verification usually lands in a few minutes, and you can set up the code below while you wait.
2. Create a key
Create an API key with the sending permission. It is shown once, so put it straight into your secrets. Store the key in credentials or ENV['SENDPOSITORY_API_KEY'].
3. Send an email
require "net/http"
require "json"
class Sendpository
URI_EMAILS = URI("https://api.sendpository.com/v1/emails")
def self.send_email(to:, subject:, html:)
req = Net::HTTP::Post.new(URI_EMAILS)
req["Authorization"] = "Bearer #{ENV.fetch('SENDPOSITORY_API_KEY')}"
req["Content-Type"] = "application/json"
req.body = { from: "Your App <hello@mail.yourdomain.com>", to: [to], subject: subject, html: html }.to_json
res = Net::HTTP.start(URI_EMAILS.host, URI_EMAILS.port, use_ssl: true, read_timeout: 10) do |http|
http.request(req)
end
body = JSON.parse(res.body)
raise body.dig("error", "message") unless res.is_a?(Net::HTTPSuccess)
body["id"]
end
endA success returns { "id": "..." } - the message’s id for looking it up later. A failure returns { "error": { "type", "message" } } with a 4xx or 5xx status.
ActiveJob, not the controller
Enqueue an ActiveJob rather than calling the API from the controller. You get retries, backoff and a failed-job record for free, and the request returns immediately.
Use `after_commit` rather than `after_save`. A job enqueued inside the transaction can run before the commit lands, and then the record it was told about is not there yet.
Testing it
- Store the key in Rails credentials or the environment - not in `config/` in plain text.
- In tests, assert the job was enqueued rather than stubbing HTTP. `ActiveJob::TestHelper` gives you `assert_enqueued_with` for exactly this.
Things to know
- Render views with ApplicationController.render(template: 'mailers/welcome', locals: {...}).
- Call it from an Active Job so retries and failures are handled for you.
Questions
ActiveJob or send from the controller?
ActiveJob. You get retries, backoff and a failed-job record without writing any of it, and the request returns immediately. Enqueue from `after_commit`, not `after_save`, or the job can run before the record is committed.
How do I send email with Ruby on Rails?
Verify your sending domain, create an API key, put it in an environment variable, and POST the message as JSON to https://api.sendpository.com/v1/emails from server-side Ruby on Rails code. The example on this page runs as written once the domain is verified.
Can I send email with Ruby on Rails without SMTP?
Yes. This is plain HTTPS, so Ruby on Rails needs no mail library and no SMTP port - which matters on hosts that block outbound 25 and 587. Failures come back as a status code on the call instead of as a bounce message hours later.
More guides
Send email with Python
Send email from Python with requests and the REST API.
Send email with Node.js
Send email from any Node.js app with the typed SDK or plain fetch.
Send your first email in minutes
6,000 emails a month (up to 200 a day), free forever. No card needed.