Email is already wired up end to end: Resend in production, `letter_opener` in development (so
messages open in your browser instead of going anywhere), and the `:test` delivery method in specs.
Adding a new transactional email means adding the message itself, not any of the plumbing around
it. The fastest way is the **`add-mailer`** skill in Claude Code, using
`app/mailers/sign_in_code_mailer.rb` and its views as the template to copy.

## Adding a mailer method

Add a method to an existing mailer, or create a new one:

```ruby
class InvoiceMailer < ApplicationMailer
  def reminder(invoice)
    @invoice = invoice
    mail(to: invoice.account.owner_email, subject: "Your invoice is due")
  end
end
```

Keep the default `from` address (it already reads from `config/initializers/app_identity.rb`);
override it per message only when you genuinely need to.

## Views

Every mailer method needs two views: `app/views/invoice_mailer/reminder.html.erb` and
`app/views/invoice_mailer/reminder.text.erb`. The plain-text version isn't optional decoration;
some clients render it, some spam filters weigh its presence, and it's part of what keeps
transactional email deliverable.

## Sending it

```ruby
InvoiceMailer.reminder(invoice).deliver_later
```

`deliver_later` sends through Solid Queue, off the request cycle, the same background-job mechanism
described in [Background Jobs](/docs/building-features/background-jobs). For a delayed send:

```ruby
InvoiceMailer.reminder(invoice).deliver_later(wait: 5.minutes)
```

See `User#send_welcome_email_later` for the pattern this kit uses to fall back to an inline send in
development and test, where waiting for a queued job to run isn't always convenient.

## Testing and previewing

Write `spec/mailers/invoice_mailer_spec.rb`, asserting the recipient, subject, and body of the
rendered message. Wherever the mailer is triggered, add a `have_enqueued_mail` assertion at that
call site. Optionally, add a preview under `spec/mailers/previews/` so you can view the rendered
email in `letter_opener` without triggering the real send path.

## Verify

`bin/check` should be green.

## Next

For every other kind of external service besides email, see
[The Adapter+Fake Pattern](/docs/building-features/the-adapter-fake-pattern).
