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):

  1. 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
  1. 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.