Three mailers, each with an HTML and a text template
Every mailer this app has, in full
app/mailers/auth/password_mailer.rb:
module Auth
class PasswordMailer < ApplicationMailer
def reset
@user = params[:user]
@reset_url = edit_auth_password_reset_url(params[:token])
mail(to: @user.email, subject: I18n.t("auth.password_resets.mail.subject"))
end
end
end
app/mailers/partners/inquiry_mailer.rb:
module Partners
class InquiryMailer < ApplicationMailer
def new_inquiry
@inquiry = params[:inquiry]
mail(to: Rails.configuration.x.email.address, reply_to: @inquiry.email,
subject: I18n.t("partners.inquiry.mail.subject", company: @inquiry.company, tier: I18n.t("partners.tiers.#{@inquiry.tier}.name")))
end
end
end
app/mailers/notifications/notification_mailer.rb:
module Notifications
class NotificationMailer < ApplicationMailer
layout "notifications_mailer"
# One email for one or several notifications of the same kind, written
# in the recipient's language.
def notify
@recipient = params[:recipient]
notifications = params[:notifications]
kind_class = notifications.first.kind_class
::Notifications::RecipientLocale.with(@recipient) do
@content = kind_class.email_content(notifications, recipient: @recipient)
@reason = I18n.t("notifications.kinds.#{kind_class.kind}.email.reason", default: "")
@unsubscribe_url = notification_unsubscribe_url(::Notifications::UnsubscribeToken.generate(user: @recipient, key: kind_class.preference_key))
@settings_url = identity_settings_url(anchor: "notifications")
headers["List-Unsubscribe"] = "<#{@unsubscribe_url}>"
headers["List-Unsubscribe-Post"] = "List-Unsubscribe=One-Click"
mail(to: @recipient.email, subject: @content.subject)
end
end
end
end
That's three mailers, this app's whole set. All three inherit from ApplicationMailer, set instance variables a view template reads, and end with a single call to mail(...). The third one does more around that call: it writes the email in the learner's language and adds the headers a mail client needs to offer a one-click unsubscribe. The shape underneath is the same.
ApplicationMailer, the shared base
# app/mailers/application_mailer.rb
class ApplicationMailer < ActionMailer::Base
default from: email_address_with_name(Rails.configuration.x.email.address, "Newbie on Rails")
layout "mailer"
end
default from: sets the sender once, and every mailer inherits it without repeating it. The address comes from one setting, config.x.email.address in config/application.rb, which reads ENV.fetch("APP_EMAIL", "[email protected]"). InquiryMailer sends to that same setting, so the sender and the inbox that receives partner inquiries can't drift apart. email_address_with_name is an Action Mailer helper that builds Newbie on Rails <[email protected]> and quotes the name when it needs quoting.
layout "mailer" is the same class-level mechanism the Layout namespacing course covered for controllers, declared on a mailer instead. NotificationMailer overrides it with layout "notifications_mailer", the way a controller can swap its parent's layout.
One HTML and one plain-text template per mailer
find app/views -path "*mailer*" -type f lists ten files. Six are per-action templates: password_mailer/reset.html.erb, password_mailer/reset.text.erb, inquiry_mailer/new_inquiry.html.erb, inquiry_mailer/new_inquiry.text.erb, notification_mailer/notify.html.erb and notification_mailer/notify.text.erb. The other four are layouts in pairs: layouts/mailer.html.erb and layouts/mailer.text.erb, shared by the first two mailers, and layouts/notifications_mailer.html.erb and layouts/notifications_mailer.text.erb for the third.
Each mailer action calls mail(...) with no format: argument. Action Mailer's convention finds both files by name and sends a multipart email: HTML for a client that renders it, and plain text as the fallback for one that doesn't. None of the mailer files asks for that explicitly.
What this course covers
Seven lessons, each checked against this app's three mailers and its installed job and queue configuration. This lesson covers the multipart setup. Lesson 2 covers the .with(...) parameterized pattern, with params[:user] and params[:token] reading the values back inside the action. Lesson 3 covers default_url_options, set differently per environment, which lets a mailer build an absolute URL with no request behind it. Lesson 4 covers deliver_later versus deliver_now, and where this app uses each, found with a grep. Lesson 5 covers Solid Queue, a durable, database-backed job backend with its own database in development and test. Lesson 6 covers config/recurring.yml, Solid Queue's scheduled-task feature, which already runs three tasks in production.
Keep going with lesson 2
with(...): how this app passes data into a mailer
How .with(...) turns keyword arguments into a params hash, and why positional calls fail against zero-parameter actions.
A free account also gives you the quizzes, your progress and notes, and the discussion.