API-powered email delivery for Ruby apps.
# Quick example
class OrderEmail < Courrier::Email
def subject = "Here is your order!"
def text = "Thanks for ordering"
def html = "<p>Thanks for ordering</p>"
end
OrderEmail.deliver to: "[email protected]"
Sponsored By Rails Designer
Add the gem:
bundle add courrier
Generate the configuration file:
bin/rails generate courrier:install
This creates config/initializers/courrier.rb
for configuring email providers and default settings.
Generate a new email:
bin/rails generate courrier:email Order
class OrderEmail < Courrier::Email
def subject = "Here is your order!"
def text
<<~TEXT
text body here
TEXT
end
def html
<<~HTML
html body here
HTML
end
end
# OrderEmail.deliver to: "[email protected]"
đź’ˇ Write your email content using the Minimal Email Editor.
Courrier uses a configuration system with three levels (from lowest to highest priority):
- Global configuration
Courrier.configure do |config|
config.provider = "postmark"
config.api_key = "xyz"
config.from = "[email protected]"
config.default_url_options = { host: "railsdesigner.com" }
# Provider-specific configuration
config.providers.loops.transactional_id = "default-template"
config.providers.mailgun.domain = "notifications.railsdesigner.com"
end
- Email class defaults
class OrderEmail < Courrier::Email
configure from: "[email protected]",
cc: "[email protected]",
provider: "mailgun",
end
- Instance options
OrderEmail.deliver to: "[email protected]",\
from: "[email protected]",\
provider: "sendgrid",\
api_key: "sk_a1b1c3"
Provider and API key settings can be overridden using environment variables (COURRIER_PROVIDER
and COURRIER_API_KEY
) for both global configuration and email class defaults.
Besides the standard email attributes (from
, to
, reply_to
, etc.), you can pass any additional attributes that will be available in your email templates:
OrderEmail.deliver to: "[email protected]",\
download_url: downloads_path(token: "token")
These custom attributes are accessible directly in your email class:
def text
<<~TEXT
#{download_url}
TEXT
end
When sending an email through Courrier, a Result
object is returned that provides information about the delivery attempt. This object offers a simple interface to check the status and access response data.
Method | Return Type | Description |
---|---|---|
success? |
Boolean | Returns true if the API request was successful |
response |
Net::HTTP::Response | The raw HTTP response from the email provider |
data |
Hash | Parsed JSON response body from the provider |
error |
Exception | Contains any error that occurred during delivery |
delivery = OrderEmail.deliver(to: "[email protected]")
if delivery.success?
puts "Email sent successfully!"
puts "Provider response: #{delivery.data}"
else
puts "Failed to send email: #{delivery.error}"
end
Courrier supports these transactional email providers:
Additional functionality to help with development and testing:
You can preview your emails in the inbox:
config.provider = "inbox"
# And add to your routes:
mount Courrier::Engine => "/courrier"
If you want to automatically open every email in your default browser:
config.provider = "inbox"
config.inbox.auto_open = true
Emails are automatically cleared with bin/rails tmp:clear
, or manually with bin/rails courrier:clear
.
Wrap your email content using layouts:
class OrderEmail < Courrier::Email
layout text: "%{content}\n\nThanks for your order!",
html: "<div>\n%{content}\n</div>"
end
Using a method:
class OrderEmail < Courrier::Email
layout html: :html_layout
def html_layout
<<~HTML
<div style='font-family: ui-sans-serif, system-ui;'>
%{content}
</div>
HTML
end
end
Using a separate class:
class OrderEmail < Courrier::Email
layout html: OrderLayout
end
class OrderLayout
self.call
<<~HTML
<div style='font-family: ui-sans-serif, system-ui;'>
%{content}
</div>
HTML
end
end
Automatically generate plain text versions from your HTML emails:
config.auto_generate_text = true # Defaults to false
Compose email addresses with display names:
class SignupsController < ApplicationController
def create
recipient = email_with_name("[email protected]", "Rails Designer Devs")
WelcomeEmail.deliver to: recipient
end
end
In Plain Ruby Objects:
class Signup
include Courrier::Email::Address
def send_welcome_email(user)
recipient = email_with_name(user.email_address, user.name)
WelcomeEmail.deliver to: recipient
end
end
Use Ruby's built-in Logger for development and testing:
config.provider = "logger" # Outputs emails to STDOUT
config.logger = custom_logger # Optional: defaults to ::Logger.new($stdout)
Create your own provider by inheriting from Courrier::Email::Providers::Base
:
class CustomProvider < Courrier::Email::Providers::Base
ENDPOINT_URL = ""
def body = ""
def headers = ""
end
Then configure it:
config.provider = "CustomProvider"
Check the existing providers for implementation examples.
Yes! While different in approach, Courrier can fully replace ActionMailer. It's a modern alternative that focuses on API-based delivery. The main difference is in how emails are structured - Courrier uses a more straightforward, class-based approach.
Not at all! While Courrier has some Rails-specific goodies (like the inbox preview feature and generators), it works great with any Ruby application.
No - Courrier is specifically built for API-based email delivery. If SMTP is needed, ActionMailer would be a better choices.
The approach is different here. Instead of separate view files, email content is defined right in the email class using text
and html
methods. Layouts can be used to share common templates. This makes emails more self-contained and easier to reason about.
Courrier offers a simpler, more modern approach to sending emails. Each email is a standalone class, configuration is straightforward (typically just only an API key is needed) and it packs few quality-of-life features (like the inbox feature and auto-generate text version).
This project uses Standard for formatting Ruby code. Please make sure to run rake
before submitting pull requests.
Courrier is released under the MIT License.