Send emails with Rails
Transactional and marketing email from a Rails service object or ActiveJob. One HTTP call, and retries never send twice.
✓Free to start. Unlimited contacts on every tier.
One request, complete trace
Request
POST /api/v1/emails
Authorization: Bearer aem_…
Idempotency-Key: welcome-8f21
{ "to": "[email protected]", "template": "welcome" }
202 Accepted
{ "id": "msg_7ca31", "status": "queued" }
[ 01 / 05 ]Quickstart
How do I send email from Rails?
Create a key, keep it on the server, and call one endpoint from a service object or ActiveJob.
Get an API key
Open Settings → API & MCP and create a key with the Send + manage permission (the default). It starts with aem_ and is shown once.
Store it as a server-side environment variable
Set AEM_KEY in the environment of your web and job processes. The code reads it with ENV.fetch, so a missing key fails loudly.
EnvironmentAEM_KEY=aem_…Send the email
Net::HTTP.post sends the request, and anything but a 2xx raises. When ActiveJob retries, the same Idempotency-Key keeps it to one email.
send_welcome.rburi = URI('https://sendandretain.com/api/v1/emails') headers = { 'Authorization' => "Bearer #{ENV.fetch('AEM_KEY')}", 'Content-Type' => 'application/json', 'Idempotency-Key' => "welcome-#{user.id}" } body = { to: user.email, template: 'welcome' }.to_json response = Net::HTTP.post(uri, body, headers) raise "Send failed: #{response.code} #{response.body}" unless response.is_a?(Net::HTTPSuccess)Check the response
A 202 means queued, not delivered. Keep the id, then follow delivery in the message log or through a signed webhook.
202 Accepted{ "id": "msg_7ca31", "status": "queued" }
[ 02 / 05 ]Where it goes
Where should email code live in your Rails app?
Service objects and jobs
A service object keeps the send visible. ActiveJob hands retries to Sidekiq, Solid Queue, or your chosen backend.
Events after commit
Send events after commit, not from model callbacks that may run inside a transaction.
A raw body for webhooks
A controller action with skip_forgery_protection reads request.raw_post.
[ 03 / 05 ]Marketing email
Can I send marketing emails from Rails too?
Yes. Send an event from the same service object when a user signs up, starts a trial, or goes quiet, and an automation sends the right email. Automations start paused, and every email goes to one person: no newsletter blasts.
- Transactional and marketing email share one contact record and one unsubscribe list.
- Unsubscribes, bounces, and complaints are suppressed for you before every send.
- Templates are react.email components; published versions never change under you.
[ 04 / 05 ]Example prompts
What can you ask your coding agent to do in Rails?
Claude Code, Cursor, and Codex can do these over the Send & Retain MCP server, with your repo open. Automations they build stay paused until you turn them on.
Welcome email
“Add a welcome email to our Rails signup using Send & Retain, with an idempotency key.”
ActiveJob
“Move our receipt email out of the model callback into an ActiveJob that calls Send & Retain after commit.”
Webhook
“Add a Rails controller that verifies Send & Retain delivery webhooks and marks bounced users.”
Trial automation
“Send a trial_started event from our Rails app and build a paused trial-conversion automation for it.”
[ 05 / 05 ]Related
Keep building with Rails
Questions people ask us
Send your first email from Rails today.
Create a key, paste the code into a service object or ActiveJob, and watch the email land in the message log.