SkillAgentSearch skills...

Courrier

API-powered email delivery for Ruby apps. With support for Mailgun, Postmark, Resend and more

Install / Use

/learn @Rails-Designer/Courrier
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Courrier

API-powered email delivery and newsletter subscription management for Ruby apps

A cute cartoon mascot wearing a blue postal uniform with red scarf and cap, carrying a leather messenger bag, representing an API-powered email delivery gem 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: "recipient@railsdesigner.com"

# Manage newsletter subscribers
Courrier::Subscriber.create "subscriber@example.com"
Courrier::Subscriber.destroy "subscriber@example.com"
<a href="https://railsdesigner.com/" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Rails-Designer/courrier/HEAD/.github/logo-dark.svg"> <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/Rails-Designer/courrier/HEAD/.github/logo-light.svg"> <img alt="Rails Designer logo" src="https://raw.githubusercontent.com/Rails-Designer/courrier/HEAD/.github/logo-light.svg" width="240" style="max-width: 100%;"> </picture> </a>

Sponsored By Rails Designer

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"

Configuration

Courrier uses a configuration system with three levels (from lowest to highest priority):

  1. Global configuration
Courrier.configure do |config|
  config.email = {
    provider: "postmark",
    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
  1. Email class defaults
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 | 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 |

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:

More Features

Additional functionality to help with development and testing:

Background jobs (Rails only)

Use deliver_later to enqueue delivering using Rails' ActiveJob. You can set various ActiveJob-supported options in the email class, like so: enqueue queue: "emails", wait: 5.minutes.

  • queue, enqueue the email on the specified queue;
  • wait, enqueue the email to be delivered with a delay;
  • wait_until, enqueue the email to be delivered at (after) a specific date/time;
  • priority, enqueues the email with the specified priority.

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

Template files

Instead of defining text and html methods, you can create ERB template files:

class OrderEmail < Courrier::Email
  def subject = "Your order is ready!"
  # text and html content will be loaded from template files
end

Create template files alongside your email class:

  • app/emails/order_email.text.erb
  • app/emails/order_email.html.erb

Templates have access to all context options and instance variables:

<!-- app/emails/order_email.html.erb -->
<h1>Hello <%= name %>!</h1>
<p>Your order #<%= order_id %> is ready for pickup.</p>

Method definitions take precedence over template files when both exist. You can mix approaches. For example, define text in a method and use a template for the html:

class OrderEmail < Courrier::Email
  def subject = "Your order is ready!"

  def text = "Hello #{name}! Your order ##{order_id} is ready."

  # html will be loaded from app/emails/order_email.html.erb
end

Markdown support

Courrier supports rendering markdown content to HTML when a markdown gem is available. Simply bundle any supported markdown gem (redcarpet, kramdown or commonmarker) and it will be used.

Markdown methods

Define a markdown method in your email class:

class OrderEmail < Courrier::Email
  def subject = "Your order is ready!"

  def markdown
    <<~MARKDOWN
      # Hello #{name}!

      Your order **##{order_id}** is ready for pickup.

      ## Order Details
      - Item: #{item_name}
      - Price: #{price}
    MARKDOWN
  end
end

Markdown templates

Create markdown template files alongside your email class:

  • app/emails/order_email.md.erb
  • app/emails/order_email.markdown.erb
<!-- app/emails/order_email.md.erb -->
# Hello <%= name %>!

Your order **#<%= order_id %>** is ready for pickup.

## Order Details
- Item: <%= item_name %>
- Price: <%= price %>

Method definitions take precedence over template files. You can mix approaches. For example, define text in a method and use a markdown template for HTML content.

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.

Newsletter subscriptions

Manage subscribers across popular email marketing platforms:

Courrier.configure do |config|
  config.subscriber = {
    provider: "buttondown",
    api_key: "your_api_key"
  }
end
# Add a subscriber
subscri
View on GitHub
GitHub Stars49
CategoryCustomer
Updated5h ago
Forks3

Languages

Ruby

Security Score

95/100

Audited on Apr 1, 2026

No findings