dchuk/rails_ai_agents · Archived

action-mailer-patterns

Implements transactional emails with Action Mailer and TDD. Use when creating email templates, notification emails, password resets, email previews, or when user mentions mailer, email, notifications, or transactional emails.

First seen Feb 13, 2026

Installation

$ npx skills add dchuk/rails_ai_agents --skill action-mailer-patterns

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from dchuk/rails_ai_agents · top by installs.

npx skills add dchuk/rails_ai_agents

Browse all from dchuk/rails_ai_agents

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Write, Edit, Bash, Glob, Grep

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,504 B
  • docs SUMMARY.md 255 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Action Mailer Patterns for Rails 8

Overview

Action Mailer handles transactional emails:

  • HTML and text email templates
  • Layouts for consistent styling
  • Previews for development
  • Background delivery via Active Job (Solid Queue)
  • Internationalized emails

Quick Start

bin/rails generate mailer User welcome password_reset

Configuration

# config/environments/development.rb
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.default_url_options = { host: "localhost", port: 3000 }

# config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { host: "example.com" }

Application Mailer

# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
  default from: "[email protected]"
  layout "mailer"

  helper_method :app_name

  private

  def app_name
    Rails.application.class.module_parent_name
  end
end

TDD Workflow

Mailer Progress:
- [ ] Step 1: Write mailer test (RED)
- [ ] Step 2: Run test (fails)
- [ ] Step 3: Create mailer method
- [ ] Step 4: Create email templates
- [ ] Step 5: Run test (GREEN)
- [ ] Step 6: Create preview

Testing Mailers (Minitest)

Mailer Test

# test/mailers/user_mailer_test.rb
require "test_helper"

class UserMailerTest < ActionMailer::TestCase
  setup do
    @user = users(:one)
  end

  test "welcome email renders headers" do
    mail = UserMailer.welcome(@user)

    assert_equal I18n.t("user_mailer.welcome.subject"), mail.subject
    assert_equal [@user.email_address], mail.to
    assert_equal ["[email protected]"], mail.from
  end

  test "welcome email renders HTML body" do
    mail = UserMailer.welcome(@user)

    assert_includes mail.html_part.body.to_s, @user.name
    assert_includes mail.html_part.body.to_s, "Welcome"
  end

  test "welcome email renders text body" do
    mail = UserMailer.welcome(@user)

    assert_includes mail.text_part.body.to_s, @user.name
  end

  test "welcome email includes login link" do
    mail = UserMailer.welcome(@user)

    assert_includes mail.html_part.body.to_s, new_session_url
  end

  test "password_reset email includes token" do
    token = "reset-token-123"
    mail = UserMailer.password_reset(@user, token)

    assert_equal [@user.email_address], mail.to
    assert_includes mail.html_part.body.to_s, token
  end
end

Testing Delivery

# test/integration/registration_test.rb
require "test_helper"

class RegistrationTest < ActionDispatch::IntegrationTest
  test "registration sends welcome email" do
    assert_enqueued_email_with UserMailer, :welcome do
      post registrations_path, params: {
        registration: { email: "[email protected]", name: "Test", password: "password123" }
      }
    end
  end
end

Testing with performenqueuedjobs

# test/integration/notification_test.rb
require "test_helper"

class NotificationTest < ActionDispatch::IntegrationTest
  test "sends notification email" do
    assert_emails 1 do
      perform_enqueued_jobs do
        NotificationMailer.daily_digest(users(:one)).deliver_later
      end
    end
  end
end

Mailer Implementation

Basic Mailer

# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  def welcome(user)
    @user = user
    @login_url = new_session_url

    mail(to: @user.email_address, subject: t(".subject"))
  end

  def password_reset(user, token)
    @user = user
    @token = token
    @reset_url = edit_password_url(token: token)
    @expires_in = "24 hours"

    mail(to: @user.email_address, subject: t(".subject"))
  end
end

Mailer with Attachments

class ReportMailer < ApplicationMailer
  def monthly_report(user, report)
    @user = user
    @report = report

    attachments["report-#{Date.current}.pdf"] = report.to_pdf

    mail(to: @user.email_address, subject: t(".subject"))
  end
end

Bundled Notification Pattern

Send one email with multiple notifications instead of many emails:

class NotificationMailer < ApplicationMailer
  def daily_digest(user)
    @user = user
    @notifications = user.notifications.unread.today

    return if @notifications.empty?

    mail(to: @user.email_address, subject: t(".subject", count: @notifications.count))
  end
end

Email Templates

<%# app/views/user_mailer/welcome.html.erb %>
<h1><%= t(".greeting", name: @user.name) %></h1>
<p><%= t(".intro") %></p>
<p><%= link_to t(".login_button"), @login_url, class: "button" %></p>
<%# app/views/user_mailer/welcome.text.erb %>
<%= t(".greeting", name: @user.name) %>

<%= t(".intro") %>

<%= t(".login_prompt") %>: <%= @login_url %>

Delivery Methods

# Background delivery (preferred)
UserMailer.welcome(user).deliver_later

# With delay
UserMailer.welcome(user).deliver_later(wait: 5.minutes)

# Immediate (avoid in production)
UserMailer.welcome(user).deliver_now

Previews

# test/mailers/previews/user_mailer_preview.rb
class UserMailerPreview < ActionMailer::Preview
  def welcome
    user = User.first
    UserMailer.welcome(user)
  end

  def password_reset
    user = User.first
    UserMailer.password_reset(user, "preview-token-123")
  end
end

Access at: http://localhost:3000/rails/mailers

I18n for Emails

# config/locales/mailers/en.yml
en:
  user_mailer:
    welcome:
      subject: "Welcome to Our App!"
      greeting: "Hello %{name}!"
      intro: "Thanks for signing up."
      login_button: "Log In Now"
      login_prompt: "Log in here"
    password_reset:
      subject: "Reset Your Password"

Localized Delivery

class UserMailer < ApplicationMailer
  def welcome(user)
    @user = user
    I18n.with_locale(user.locale || I18n.default_locale) do
      mail(to: @user.email_address, subject: t(".subject"))
    end
  end
end

Checklist

  • Mailer test written first (RED)
  • Mailer method created
  • HTML template created
  • Text template created
  • Uses I18n for all text
  • Preview created
  • Uses deliverlater (not delivernow)
  • All tests GREEN