Courrier
API-powered email delivery for Ruby apps. With support for Mailgun, Postmark, Resend and more.
Installation
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.
Usage
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: "recipient@railsdesigner.com"
đź’ˇ Write your email content using the Minimal Email Editor.
Configuration
Courrier uses a configuration system with three levels (from lowest to highest priority):
- Global configuration ```ruby Courrier.configure do |config| config.provider = “postmark” config.api_key = “xyz” config.from = “devs@railsdesigner.com” 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
2. **Email class defaults**
```ruby
class OrderEmail < Courrier::Email
configure from: "orders@railsdesigner.com",
cc: "records@railsdesigner.com",
provider: "mailgun",
end
- Instance options
OrderEmail.deliver to: "recipient@railsdesigner.com",\ from: "shop@railsdesigner.com",\ 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.
Custom Attributes
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: "recipient@railsdesigner.com",\
download_url: downloads_path(token: "token")
These custom attributes are accessible directly in your email class:
def text
<<~TEXT
#{download_url}
TEXT
end
Result Object
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.
Available Methods
Method | Return Type | Description |
---|---|---|
success? |
Boolean | Returns true if the API request was successful |
response |
NetHTTPResponse | 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 |
Example
delivery = OrderEmail.deliver(to: "recipient@example.com")
if delivery.success?
puts "Email sent successfully!"
puts "Provider response: #{delivery.data}"
else
puts "Failed to send email: #{delivery.error}"
end
Providers
Courrier supports these transactional email providers:
⚠️ Some providers still need manual verification of their implementation. If you’re using one of these providers, please help verify the implementation by sharing your experience in this GitHub issue. 🙏
More Features
Additional functionality to help with development and testing:
Inbox (Rails only)
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
.
Layout Support
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
Auto-generate Text from HTML
Automatically generate plain text versions from your HTML emails:
config.auto_generate_text = true # Defaults to false
Email Address Helper
Compose email addresses with display names:
class SignupsController < ApplicationController
def create
recipient = email_with_name("devs@railsdesigner.com", "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
Logger Provider
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)
Custom Providers
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.