In a Hanami app, mailers are responsible for sending email. Each mailer is a class that describes an email: who it’s from and to, its subject, its HTML and text bodies, and any attachments. You send it by calling deliver with the data the email needs.
Mailers render their bodies with Hanami View, so their templates share your app’s view context, parts, scopes and helpers, including i18n. They deliver through a delivery method the app configures for you.
Generating a mailer
Use the mailer generator to create a mailer and its templates:
$ bundle exec hanami generate mailer welcome
This creates three files:
-
app/mailers/welcome.rb— the mailer class -
app/templates/mailers/welcome.html.erb— the HTML body template -
app/templates/mailers/welcome.text.erb— the text body template
Mailers inherit from a base mailer class defined in app/mailer.rb:
# app/mailers/welcome.rb
end
end
end
Pass --slice=admin to generate into a slice, and --template-engine=haml (or slim) to use a different template engine for the HTML body. See CLI commands for more.
Your first mailer
Let’s flesh out the welcome mailer. We want it to greet a new user by name, so we declare the headers and expose the user to the templates:
# app/mailers/welcome.rb
from "welcome@bookshelf.test"
to { user[:email] }
subject { "Welcome to Bookshelf, !" }
expose :user
end
end
end
The bodies come from the templates, which render just like any other Hanami view template:
<%# app/templates/mailers/welcome.html.erb %>
Welcome, !
We're glad to have you at Bookshelf.
<%# app/templates/mailers/welcome.text.erb %>
Welcome, !
We're glad to have you at Bookshelf.
By default both formats are rendered, producing a multipart email with HTML and text alternatives.
Delivering a mailer
Mailers are registered as components, so you can resolve them from the app container or inject them with Deps. Call deliver, passing the data the mailer needs:
welcome_mailer = Hanami.app["mailers.welcome"]
welcome_mailer.deliver(user: {name: "Alice", email: "alice@example.com"})
More often you’ll inject the mailer where you need it — say, from an operation:
include Deps[mailer: "mailers.welcome"]
user = yield create_user(attributes)
mailer.deliver(user:)
Success(user)
end
# ...
end
end
end
The data you pass to deliver (here, user:) flows to your headers, templates, attachments and delivery options. See Exposures and input for details.
Next steps
-
Exposures and input — how the data you pass to
deliverreaches your headers, templates, attachments and delivery options. - Headers — standard and custom email headers, computed dynamically or overridden at delivery time.
- Templates and rendering — HTML and text bodies, formats, view integration, and rendering without Hanami View.
- Attachments — static, dynamic, inline and runtime attachments.
- Delivery — delivery methods, SMTP configuration, delivery options, and preparing messages without sending.
- Testing — asserting on the email your app sends.