Courrier: a gem to send emails without SMTP
Every transactional email provider ships a Ruby SDK. Each one has its own client class, its own conventions, its own way of doing the same thing. I got tired of learning yet another API for every project. So I built Courrier.
About 14 months and 73 commits later, Courrier 1.0 is here. It covers 13 email providers and 7 newsletter platforms. There’s a companion gem for Rails apps that adds generators, ActiveJob support, browser-based inbox previews and more.
13 providers, one API
Courrier.configure do |config|
config.email = {
provider: :postmark,
api_key: "your_postmark_api_key"
}
config.from = "devs@railsdesigner.com"
end
# courrier/emails/order_email.rb
class OrderEmail < Courrier::Email
def subject = "Your order is ready!"
def text
<<~TEXT
Thanks for ordering, #{name}!
Your order ##{order_id} is on its way.
TEXT
end
def html
<<~HTML
<h1>Thanks for ordering!</h1>
<p>Your order ##{order_id} is on its way.</p>
HTML
end
end
OrderEmail.deliver to: "customer@railsdesigner.com", name: "Cam", order_id: 42
That’s it. That’s the whole thing. One class, one deliver call, works with any supported provider.
Courrier has three levels of configuration that build on each other. Set defaults globally, override per email class or per delivery. Need to use Mailpace for transactional emails and Postmark for marketing? Easy. Need a provider not on the list? Subclass Courrier::Email::Providers::Base and add it yourself.
Content your way
The example above uses text and html methods. That’s the simplest path and works for most cases.
Prefer markdown? Define a markdown method instead. Courrier detects your markdown engine (kramdown, redcarpet or commonmarker) automatically and renders it to HTML.
Want the same structure as ViewComponent gives you (an ERB template alongside your email class):
courrier/emails/order_email.rb
courrier/emails/order_email.html.erb
Method definitions take precedence over template files, so you can mix approaches. Plain text via a method, HTML via a template. Or both via templates. Whatever fits your mental model.
Layouts wrap your email content the same way Rails layouts wrap views. Define one inline, in a method or in a separate class. And if you only write HTML, Courrier can auto generate the plain text version. 🤖
But wait, there is more
The Result object tells you if delivery succeeded, with access to the raw response data and any errors. Test helpers give you assert_emails_delivered and friends, so you can verify delivery without hitting a real API. before_deliver and after_deliver callbacks let you hook into the lifecycle. Custom HTTP headers (like List-Unsubscribe) go straight into each email class.
There’s also a a newsletter subscription system: Courrier::Subscriber.create and .destroy work with Beehiiv, Buttondown, Kit, Loops, Mailchimp, MailerLite and Brevo.
Rails Courrier
Courrier works with any Ruby app. But if you’re using Rails, there’s a companion gem that adds Rails-specific features.

Generators scaffold everything for you. Run rails generate courrier:install to create the initializer. Pass --provider to pre-fill provider-specific config. Run rails generate courrier:email Order to create an email class.
ActiveJob support means you can send emails in the background with a single method change. Call deliver_later instead of deliver.
Inbox gives you browser-based email previews, like (good ol’) Letter Opener but built into the gem. Mount the engine in your routes and every sent email opens in your browser.
I18n is scoped under courrier.email.<class_name>, so your translations stay organised. The t helper works in email classes and ERB templates.
Instrumentation publishes delivery.courrier and delivery_failed.courrier events through ActiveSupport::Notifications.
I have a few ideas for what is next. Auto redundancy: if your primary provider goes down, Courrier falls back to a backup provider. Baked-in layouts to make your emails a bit fancier (without asking a LLM). Dedicated real email testing tools that go beyond the test helpers. And more delivery methods beyond email (SMS, push notifications). 🤯
A huge thank you to delynn, benedikt, faheemKamboh and JSap0914 for their contributions. ❤️
Give Courrier a try. Star the repo on GitHub. For Rails apps, use rails_courrier. Would love to see what you build with it. 🚀🤘
Want to read me more?
-
Salut Courrier! A New Ruby Gem to Send Emails
Introducing Courrier. A modern way to send emails in Ruby apps. With support for many providers like Mailgun, Postmark and Sendgrid. -
Add newsletter subscriptions to Rails 8 signups
Let users subscribe to your newsletter during signup. Store preferences securely with Rails Vault and manage subscriptions with Courrier. -
Create an Email Drip Campaign Using Rails Vault
Email drip campaigns are a powerful marketing tool for web apps. In this article I give the lowdown how to create one yourself using the Rails Vault gem.
Over to you…
What did you like about this article? Learned something knew? Found something is missing or even broken? 🫣 Let me (and others) know!
Comments are powered by Chirp Form
{{comment}}