class ActionMailer::Base
Базовый класс Action Mailer
Action Mailer позволяет отправлять электронные письма из приложения с помощью модели почтовой программы и представлений.
Модели почтовых программ
Чтобы использовать Action Mailer, необходимо создать модель почтовой программы.
$ bin/rails generate mailer Notifier
Сгенерированная модель наследуется от ApplicationMailer, который, в свою очередь, наследуется от ActionMailer::Base. Модель почтовой программы определяет методы, используемые для создания сообщения электронной почты. В этих методах можно задать переменные, которые будут использоваться в представлениях почтовой программы, параметры самого письма, такие как адрес :from, и вложения.
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end
class NotifierMailer < ApplicationMailer
default from: 'no-reply@example.com',
return_path: 'system@example.com'
def welcome(recipient)
@account = recipient
mail(to: recipient.email_address_with_name,
bcc: ["bcc@example.com", "Order Watcher <watcher@example.com>"])
end
end
В методе почтовой программы доступны следующие методы:
-
attachments[]=— позволяет удобным способом добавлять вложения к письму;attachments['filename.png'] = File.read('path/to/filename.png') -
attachments.inline[]=— позволяет добавлять встроенное вложение к письму так же, как иattachments[]= -
headers[]=— позволяет указать любое поле заголовка письма, напримерheaders['X-No-Spam'] = 'True'. Обратите внимание: повторное объявление заголовка добавит несколько полей с одинаковым именем. Дополнительные сведения см. в документацииheaders. -
headers(hash)— позволяет указать несколько заголовков письма, напримерheaders({'X-No-Spam' => 'True', 'In-Reply-To' => '1234@message.id'}) -
mail— позволяет указать адрес электронной почты для отправки.
Хэш, передаваемый методу mail, позволяет указать любой заголовок, который принимает Mail::Message (любой допустимый заголовок электронной почты, включая необязательные поля).
Если методу mail не передан блок, он проверит представления и отправит все представления с тем же именем, что и метод. Поэтому описанное выше действие отправит файл представления welcome.text.erb, а также файл представления welcome.html.erb в письме формата multipart/alternative.
Если нужно явно отобразить только определённые шаблоны, передайте блок:
mail(to: user.email) do |format| format.text format.html end
Синтаксис с блоком также полезен, если нужно задать информацию для отдельной части:
mail(to: user.email) do |format| format.text(content_transfer_encoding: "base64") format.html end
Или даже отобразить специальное представление:
mail(to: user.email) do |format|
format.text
format.html { render "some_other_template" }
end
Представления почтовых программ
Как и в Action Controller, у каждого класса почтовой программы есть соответствующий каталог представлений, в котором каждый метод класса ищет шаблон со своим именем.
Чтобы определить шаблон для почтовой программы, создайте файл .erb с тем же именем, что и метод в модели почтовой программы. Например, в почтовой программе, определённой выше, для создания письма будет использоваться шаблон app/views/notifier_mailer/welcome.text.erb.
Переменные, определённые в методах модели почтовой программы, доступны в соответствующем представлении как переменные экземпляра.
По умолчанию письма отправляются в виде обычного текста, поэтому пример представления для нашей модели может выглядеть так:
Hi <%= @account.name %>, Thanks for joining our service! Please check back often.
В этих представлениях можно использовать даже вспомогательные методы Action View. Например:
You got a new note! <%= truncate(@note.body, length: 25) %>
Если в представлении нужен доступ к теме, отправителю или получателям, это можно сделать через объект message:
You got a new note from <%= message.from %>! <%= truncate(@note.body, length: 25) %>
Создание URL-адресов
В представлениях почтовых программ можно создавать URL-адреса с помощью url_for или именованных маршрутов. В отличие от контроллеров Action Pack, экземпляр почтовой программы не имеет контекста входящего запроса, поэтому для создания URL-адреса необходимо указать все нужные данные.
При использовании url_for необходимо указать :host, :controller и :action:
<%= url_for(host: "example.com", controller: "welcome", action: "greeting") %>
При использовании именованных маршрутов нужно указать только :host:
<%= users_url(host: "example.com") %>
Следует использовать стиль named_route_url (создающий абсолютные URL-адреса) и избегать стиля named_route_path (создающего относительные URL-адреса), поскольку у пользователей, читающих письмо, не будет текущего URL-адреса, относительно которого можно определить путь.
Также можно задать хост по умолчанию, который будет использоваться во всех почтовых программах, указав параметр :host в качестве параметра конфигурации в config/application.rb:
config.action_mailer.default_url_options = { host: "example.com" }
Можно также определить метод default_url_options в отдельных почтовых программах, чтобы переопределить эти значения по умолчанию для конкретной программы.
По умолчанию, если config.force_ssl равно true, для URL-адресов с хостами используется протокол HTTPS.
Отправка писем
После определения действия почтовой программы и шаблона можно отправить сообщение или отложить его создание и отправку на более позднее время:
NotifierMailer.welcome(User.first).deliver_now # sends the email mail = NotifierMailer.welcome(User.first) # => an ActionMailer::MessageDelivery object mail.deliver_now # generates and sends the email now
Класс ActionMailer::MessageDelivery — это оболочка над делегатом, который вызовет ваш метод для создания письма. Если нужен прямой доступ к делегатору или Mail::Message, можно вызвать метод message объекта ActionMailer::MessageDelivery.
NotifierMailer.welcome(User.first).message # => a Mail::Message object
Action Mailer хорошо интегрирован с Active Job, поэтому письма можно создавать и отправлять в фоновом режиме (например, вне цикла обработки запроса, чтобы пользователю не пришлось ждать):
NotifierMailer.welcome(User.first).deliver_later # enqueue the email sending to Active Job
Обратите внимание: deliver_later выполнит ваш метод в фоновой задаче.
Экземпляр класса почтовой программы не создаётся. Вместо этого нужно вызвать метод, определённый непосредственно в самом классе. Ожидается, что все методы экземпляра будут возвращать объект сообщения для отправки.
Многокомпонентные письма
Многокомпонентные сообщения также можно создавать неявно: Action Mailer автоматически обнаружит и использует многокомпонентные шаблоны, имя каждого из которых состоит из имени действия и типа содержимого. Каждый обнаруженный шаблон будет добавлен в сообщение как отдельная часть.
Например, если существуют следующие шаблоны:
-
signup_notification.text.erb
-
signup_notification.html.erb
-
signup_notification.xml.builder
-
signup_notification.yml.erb
Каждый из них будет обработан и добавлен в сообщение как отдельная часть с соответствующим типом содержимого. Тип содержимого всего сообщения автоматически устанавливается в multipart/alternative, что означает, что письмо содержит несколько различных представлений одного и того же тела письма. Во все шаблоны письма передаются одни и те же переменные экземпляра, определённые в действии.
Неявный рендеринг шаблонов не выполняется, если к письму добавлены вложения или части. Это значит, что каждую часть письма нужно будет добавить вручную, а тип содержимого письма установить в multipart/alternative.
Вложения
Отправлять вложения в письмах просто:
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments['free_book.pdf'] = File.read('path/to/file.pdf')
mail(to: recipient, subject: "New account information")
end
end
Если в каталоге представлений есть шаблоны welcome.text.erb и welcome.html.erb, будет отправлено письмо формата multipart/mixed с двумя частями: первая часть будет multipart/alternative с текстовым и HTML-представлениями письма внутри, а вторая — application/pdf с файлом file.pdf, закодированным в Base64, и именем файла free_book.pdf.
Чтобы отправить вложения без содержимого, необходимо создать для них пустое представление или добавить пустой параметр body, например:
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments['free_book.pdf'] = File.read('path/to/file.pdf')
mail(to: recipient, subject: "New account information", body: "")
end
end
Можно также отправлять вложения вместе с HTML-шаблоном. В этом случае необходимо добавить body, вложения и пользовательский тип содержимого, например:
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments["free_book.pdf"] = File.read("path/to/file.pdf")
mail(to: recipient,
subject: "New account information",
content_type: "text/html",
body: "<html><body>Hello there</body></html>")
end
end
Встроенные вложения
Также можно указать, что файл следует показывать встроенным в другой HTML-контент. Это полезно, если нужно отобразить корпоративный логотип или фотографию.
class NotifierMailer < ApplicationMailer
def welcome(recipient)
attachments.inline['photo.png'] = File.read('path/to/photo.png')
mail(to: recipient, subject: "Here is what we look like")
end
end
Затем, чтобы вставить изображение в представление, создайте файл welcome.html.erb и вызовите image_tag, передав ему вложение, которое нужно отобразить. После этого вызовите url для вложения, чтобы получить относительный путь к идентификатору содержимого для источника изображения:
<h1>Please Don't Cringe</h1> <%= image_tag attachments['photo.png'].url -%>
Поскольку используется метод image_tag из Action View, можно передать любые другие нужные параметры:
<h1>Please Don't Cringe</h1> <%= image_tag attachments['photo.png'].url, alt: 'Our Photo', class: 'photo' -%>
Наблюдение за письмами и их перехват
Action Mailer предоставляет хуки для методов наблюдателя и перехватчика Mail. Они позволяют зарегистрировать классы, вызываемые на разных этапах жизненного цикла доставки письма.
Класс наблюдателя должен реализовать метод :delivered_email(message), который будет вызван один раз для каждого отправленного письма после его отправки.
Класс перехватчика должен реализовать метод :delivering_email(message), который будет вызван до отправки письма, что позволит изменить письмо до его передачи службам доставки. Класс должен вносить необходимые изменения непосредственно в переданный экземпляр Mail::Message.
Хэш параметров по умолчанию
Action Mailer задаёт для писем ряд разумных значений по умолчанию. Обычно их указывают в методе default внутри определения класса:
class NotifierMailer < ApplicationMailer default sender: 'system@example.com' end
Можно передать любое значение заголовка, которое принимает Mail::Message. По умолчанию ActionMailer::Base задаёт следующие значения:
-
mime_version: "1.0" -
charset: "UTF-8" -
content_type: "text/plain" -
parts_order: [ "text/plain", "text/enriched", "text/html" ]
parts_order и charset фактически не являются допустимыми полями заголовка Mail::Message, но Action Mailer соответствующим образом преобразует их и задаёт правильные значения.
Поскольку можно передать любой заголовок, его необходимо заключить в кавычки как строку или передать в виде символа с подчёркиваниями, поэтому следующий вариант будет работать:
class NotifierMailer < ApplicationMailer
default 'Content-Transfer-Encoding' => '7bit',
content_description: 'This is a description'
end
Наконец, Action Mailer также поддерживает передачу объектов Proc и Lambda в хэш параметров по умолчанию, поэтому можно определять методы, значения которых вычисляются во время создания сообщения:
class NotifierMailer < ApplicationMailer
default 'X-Special-Header' => Proc.new { my_method }, to: -> { @inviter.email_address }
private
def my_method
'some complex call'
end
end
Обратите внимание: proc/lambda вычисляется сразу в начале создания почтового сообщения. Поэтому если установить значение в хэше параметров по умолчанию с помощью proc, а затем установить то же значение в методе почтовой программы, значение из хэша будет перезаписано методом почтовой программы.
Также можно задать параметры по умолчанию, которые будут использоваться во всех почтовых программах, с помощью конфигурации default_options= в config/application.rb:
config.action_mailer.default_options = { from: "no-reply@example.org" }
Обратные вызовы
Для настройки сообщений можно указать обратные вызовы с помощью before_action и after_action, а для обёртывания процесса доставки — с помощью before_deliver и after_deliver. Например, если нужно добавить стандартные встроенные вложения и вести журнал доставки для всех сообщений, отправляемых определённым классом почтовой программы:
class NotifierMailer < ApplicationMailer
before_action :add_inline_attachment!
after_deliver :log_delivery
def welcome
mail
end
private
def add_inline_attachment!
attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
end
def log_delivery
Rails.logger.info "Sent email with message id '#{message.message_id}' at #{Time.current}."
end
end
Обратные вызовы действий в Action Mailer реализованы с помощью AbstractController::Callbacks, поэтому их можно определять и настраивать так же, как обратные вызовы в классах, наследующихся от ActionController::Base.
Обратите внимание: если у вас нет особой причины поступать иначе, в классах Action Mailer следует использовать before_action вместо after_action, чтобы заголовки разбирались правильно.
Обработка ошибок
Блоки rescue внутри метода почтовой программы не могут перехватывать ошибки, возникающие вне этапа рендеринга, например ошибки десериализации записи в фоновой задаче или ошибки сторонней службы доставки почты.
Чтобы перехватывать ошибки, возникающие на любом этапе отправки письма, используйте rescue_from:
class NotifierMailer < ApplicationMailer
rescue_from ActiveJob::DeserializationError do
# ...
end
rescue_from "SomeThirdPartyService::ApiError" do
# ...
end
def notify(recipient)
mail(to: recipient, subject: "Notification")
end
end
Предварительный просмотр писем
Можно визуально просматривать шаблоны писем, добавив файл предварительного просмотра почтовой программы в ActionMailer::Base.preview_paths. Поскольку большинство писем использует данные из базы данных, для загрузки сообщений с фиктивными данными необходимо написать несколько сценариев:
class NotifierMailerPreview < ActionMailer::Preview
def welcome
NotifierMailer.welcome(User.first)
end
end
Методы должны возвращать объект Mail::Message, который можно получить, вызвав метод почтовой программы без дополнительных deliver_now / deliver_later. Расположение каталогов предварительного просмотра почтовых программ можно настроить с помощью параметра preview_paths, значение которого по умолчанию — test/mailers/previews:
config.action_mailer.preview_paths << "#{Rails.root}/lib/mailer_previews"
Обзор всех вариантов предварительного просмотра доступен по адресу http://localhost:3000/rails/mailers на работающем сервере разработки.
Объекты Previews также можно перехватывать аналогично доставляемым письмам, зарегистрировав перехватчик предварительного просмотра с методом previewing_email:
class CssInlineStyler
def self.previewing_email(message)
# inline CSS styles
end
end
config.action_mailer.preview_interceptors :css_inline_styler
Обратите внимание: перехватчики необходимо регистрировать и с помощью register_interceptor, и с помощью register_preview_interceptor, если они должны применяться как при отправке, так и при предварительном просмотре писем.
Параметры конфигурации
Эти параметры задаются на уровне класса, например ActionMailer::Base.raise_delivery_errors = true
-
default_options— этот параметр можно задать на уровне класса, а также внутри самого класса, как описано в предыдущем разделе. -
logger— журнал используется для записи информации о процессе отправки почты, если он доступен. Для отключения ведения журнала можно задать значениеnil. Совместим как со встроенным в RubyLogger, так и с журналами Log4r. -
smtp_settings— позволяет подробно настроить способ доставки:smtp:-
:address— позволяет использовать удалённый почтовый сервер. Для этого измените значение по умолчанию — «localhost». -
:port— если почтовый сервер работает не на порту 25, здесь можно указать другой порт. -
:domain— здесь можно указать домен HELO, если это необходимо. -
:user_name— если для почтового сервера требуется аутентификация, укажите здесь имя пользователя. -
:password— если для почтового сервера требуется аутентификация, укажите здесь пароль. -
:authentication— если для почтового сервера требуется аутентификация, здесь необходимо указать её тип. Это символ, принимающий одно из значений::plain(пароль будет отправлен в кодировке Base64),:login(пароль будет отправлен в кодировке Base64) или:cram_md5(объединяет механизм Challenge/Response для обмена данными и криптографический алгоритм MessageDigest5 для хеширования важных данных). -
:enable_starttls— использовать STARTTLS при подключении к SMTP-серверу и завершать работу с ошибкой, если протокол не поддерживается. По умолчанию задано значениеfalse. Требуется версия 2.7 или выше гем-пакетаMail. -
:enable_starttls_auto— проверять, включён ли STARTTLS на SMTP-сервере, и начинать его использовать, если это так. По умолчанию задано значениеtrue. -
:openssl_verify_mode— при использовании TLS можно задать способ проверки сертификата OpenSSL. Это особенно полезно, если необходимо проверить самоподписанный сертификат и/или сертификат с подстановочными знаками. Можно указать имя константы проверки OpenSSL ('none'или'peer') либо непосредственно константу (OpenSSL::SSL::VERIFY_NONEилиOpenSSL::SSL::VERIFY_PEER). -
:ssl/:tlsПозволяет SMTP-подключению использовать SMTP/TLS (SMTPS: SMTP через прямое TLS-подключение). -
:open_timeoutКоличество секунд ожидания при попытке установить соединение. -
:read_timeoutКоличество секунд ожидания до истечения времени ожидания вызова read(2).
-
-
sendmail_settings— позволяет переопределить параметры способа доставки:sendmail.-
:location— расположение исполняемого файла sendmail. По умолчанию —/usr/sbin/sendmail. -
:arguments— аргументы командной строки. По умолчанию —%w[ -i ]; перед отправкой сообщения автоматически добавляется-f sender@address.
-
-
file_settings— позволяет переопределить параметры способа доставки:file.-
:location— каталог, в который будут записываться письма. По умолчанию используется каталог приложенияtmp/mails.
-
-
raise_delivery_errors— следует ли генерировать ошибки, если не удалось доставить письмо. -
delivery_method— определяет способ доставки. Возможные значения::smtp(по умолчанию),:sendmail,:testи:file. Также можно передать пользовательский объект способа доставки, напримерMyOwnDeliveryMethodClass. Сведения об интерфейсе, который необходимо реализовать для пользовательского агента доставки, см. в документации гемаMail. -
perform_deliveries— определяет, отправляет ли Action Mailer письма фактически при вызове.deliverдля сообщения электронной почты или метода Action Mailer. По умолчанию отправка включена, но её можно отключить для упрощения функционального тестирования. -
deliveries— хранит массив всех писем, отправленных через Action Mailer с помощьюdelivery_method :test. Наиболее полезно для модульного и функционального тестирования. -
delivery_job— класс задачи, используемый вместе сdeliver_later. Почтовые программы могут задать здесь пользовательскую задачу доставки. По умолчанию используетсяActionMailer::MailDeliveryJob. -
deliver_later_queue_name— имя очереди, используемойdeliver_laterсо значениемdelivery_jobпо умолчанию. Почтовые программы могут задать пользовательское имя очереди.
Константы
- PROTECTED_IVARS
Атрибуты
Позволяет задать имя текущего почтового объекта.
Открытые методы класса
# File actionmailer/lib/action_mailer/base.rb, line 581 def default(value = nil) self.default_params = default_params.merge(value).freeze if value default_params end
Позволяет задавать значения по умолчанию через конфигурацию приложения:
config.action_mailer.default_options = { from: "no-reply@example.org" }
# File actionmailer/lib/action_mailer/base.rb, line 603
def email_address_with_name(address, name)
Mail::Address.new.tap do |builder|
builder.address = address
builder.display_name = name.presence
end.to_s
end Возвращает адрес электронной почты в формате «Имя <email@example.com>».
Если имя — пустая строка, возвращает только адрес.
# File actionmailer/lib/action_mailer/base.rb, line 571 def mailer_name @mailer_name ||= anonymous? ? "anonymous" : name.underscore end
Возвращает имя текущего почтового объекта. Этот метод также используется в качестве пути для поиска представления. Если почтовый объект анонимный, метод вернёт вместо этого anonymous.
# File actionmailer/lib/action_mailer/base.rb, line 639 def initialize super() @_mail_was_called = false @_message = Mail.new end
# File actionmailer/lib/action_mailer/base.rb, line 548 def register_interceptor(interceptor) Mail.register_interceptor(observer_class_for(interceptor)) end
Регистрирует перехватчик, который будет вызван перед отправкой письма. В качестве перехватчика можно передать класс, строку или символ. Если передана строка или символ, они будут преобразованы в CamelCase, а затем в константу.
# File actionmailer/lib/action_mailer/base.rb, line 522
def register_interceptors(*interceptors)
interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
end Регистрирует один или несколько перехватчиков, которые будут вызваны перед отправкой письма.
# File actionmailer/lib/action_mailer/base.rb, line 534 def register_observer(observer) Mail.register_observer(observer_class_for(observer)) end
Регистрирует наблюдателя, который получит уведомление о доставке письма. В качестве наблюдателя можно передать класс, строку или символ. Если передана строка или символ, они будут преобразованы в CamelCase, а затем в константу.
# File actionmailer/lib/action_mailer/base.rb, line 512
def register_observers(*observers)
observers.flatten.compact.each { |observer| register_observer(observer) }
end Регистрирует одного или нескольких наблюдателей, которые получат уведомление о доставке письма.
# File actionmailer/lib/action_mailer/base.rb, line 938 def self.supports_path? # :doc: false end
В письмах не поддерживаются ссылки с относительными путями.
# File actionmailer/lib/action_mailer/base.rb, line 555 def unregister_interceptor(interceptor) Mail.unregister_interceptor(observer_class_for(interceptor)) end
Отменяет регистрацию ранее зарегистрированного перехватчика. В качестве перехватчика можно передать класс, строку или символ. Если передана строка или символ, они будут преобразованы в CamelCase, а затем в константу.
# File actionmailer/lib/action_mailer/base.rb, line 527
def unregister_interceptors(*interceptors)
interceptors.flatten.compact.each { |interceptor| unregister_interceptor(interceptor) }
end Отменяет регистрацию одного или нескольких ранее зарегистрированных перехватчиков.
# File actionmailer/lib/action_mailer/base.rb, line 541 def unregister_observer(observer) Mail.unregister_observer(observer_class_for(observer)) end
Отменяет регистрацию ранее зарегистрированного наблюдателя. В качестве наблюдателя можно передать класс, строку или символ. Если передана строка или символ, они будут преобразованы в CamelCase, а затем в константу.
# File actionmailer/lib/action_mailer/base.rb, line 517
def unregister_observers(*observers)
observers.flatten.compact.each { |observer| unregister_observer(observer) }
end Отменяет регистрацию одного или нескольких ранее зарегистрированных наблюдателей.
Открытые методы экземпляра
# File actionmailer/lib/action_mailer/base.rb, line 756
def attachments
if @_mail_was_called
LateAttachmentsProxy.new(@_message.attachments)
else
@_message.attachments
end
end Позволяет добавлять вложения к письму, например:
mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
В этом случае Mail определит имя файла и соответствующий тип MIME. Кроме того, будут установлены Content-Type, Content-Disposition и Content-Transfer-Encoding, а содержимое вложения будет закодировано в Base64.
При необходимости можно задать переопределения, передав хеш вместо строки:
mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
content: File.read('/path/to/filename.jpg')}
Если требуется использовать кодирование, отличное от Base64, необходимо передать тип кодирования вместе с предварительно закодированным содержимым, так как Mail не умеет декодировать данные:
file_content = SpecialEncode(File.read('/path/to/filename.jpg'))
mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: file_content }
Также можно найти определённые вложения:
# By Filename mail.attachments['filename.jpg'] # => Mail::Part object or nil # or by index mail.attachments[0] # => Mail::Part (first attachment)
# File actionmailer/lib/action_mailer/base.rb, line 680 def email_address_with_name(address, name) self.class.email_address_with_name(address, name) end
Возвращает адрес электронной почты в формате «Имя <email@example.com>».
Если имя — пустая строка, возвращает только адрес.
# File actionmailer/lib/action_mailer/base.rb, line 718
def headers(args = nil)
if args
@_message.headers(args)
else
@_message
end
end Позволяет передавать случайные и нестандартные заголовки новому объекту Mail::Message, который добавит их к себе.
headers['X-Special-Domain-Specific-Header'] = "SecretValue"
В headers также можно передать хеш с именами и значениями полей заголовка, которые затем будут установлены для объекта Mail::Message:
headers 'X-Special-Domain-Specific-Header' => "SecretValue",
'In-Reply-To' => incoming.message_id
В результате заголовок Mail::Message будет содержать следующее:
X-Special-Domain-Specific-Header: SecretValue
Примечание о замене уже заданных заголовков:
-
subject -
sender -
from -
to -
cc -
bcc -
reply-to -
orig-date -
message-id -
references
Каждое поле может встречаться в заголовках письма только один раз, тогда как другие поля, например X-Anything, могут встречаться несколько раз.
Чтобы заменить уже существующий заголовок, сначала задайте для него значение nil, чтобы сбросить текущее значение. В противном случае для того же заголовка будет добавлено ещё одно поле.
# File actionmailer/lib/action_mailer/base.rb, line 865
def mail(headers = {}, &block)
return message if @_mail_was_called && headers.blank? && !block
# At the beginning, do not consider class default for content_type
content_type = headers[:content_type]
headers = apply_defaults(headers)
# Apply charset at the beginning so all fields are properly quoted
message.charset = charset = headers[:charset]
# Set configure delivery behavior
wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options])
assign_headers_to_message(message, headers)
# Render the templates and blocks
responses = collect_responses(headers, &block)
@_mail_was_called = true
create_parts_from_responses(message, responses)
wrap_inline_attachments(message)
# Set up content type, reapply charset and handle parts order
message.content_type = set_content_type(message, content_type, headers[:content_type])
message.charset = charset
if message.multipart?
message.body.set_sort_order(headers[:parts_order])
message.body.sort_parts!
end
message
end Основной метод, который создаёт сообщение и отображает шаблоны электронного письма. Его можно вызвать двумя способами: с блоком или без него.
Метод принимает хеш заголовков. Этот хеш позволяет указать наиболее часто используемые заголовки сообщения электронной почты:
-
:subject— тема сообщения. Если она не указана, Action Mailer запросит у класса Rails I18n перевод:subjectв области[mailer_scope, action_name]или, если перевод отсутствует, переведёт человекочитаемый вариантaction_name -
:to— адресат сообщения; может быть строкой с адресами или массивом адресов. -
:from— отправитель сообщения. -
:cc— адресаты копии письма; может быть строкой с адресами или массивом адресов. -
:bcc— адресаты скрытой копии письма; может быть строкой с адресами или массивом адресов. -
:reply_to— адрес, который будет указан в заголовке письмаReply-To. -
:date— дата отправки письма.
Для любого из перечисленных выше заголовков (кроме :date) можно задать значения по умолчанию с помощью метода класса ::default:
class Notifier < ActionMailer::Base
default from: 'no-reply@test.lindsaar.net',
bcc: 'email_logger@test.lindsaar.net',
reply_to: 'bounces@test.lindsaar.net'
end
Если нужны другие заголовки, не перечисленные выше, их можно передать в хеше заголовков или использовать метод headers['name'] = value.
Если в качестве заголовка указан :return_path, это значение будет использоваться как адрес отправителя конверта для сообщения Mail. Это полезно, если уведомления о доставке должны приходить на адрес, отличный от указанного в :from. Mail будет использовать :return_path вместо :sender, а его, в свою очередь, — вместо поля :from в качестве значения отправителя конверта.
Если методу mail не передан блок, он найдёт все шаблоны в путях поиска представлений, используя по умолчанию имя почтового объекта и имя вызываемого метода. Затем он автоматически создаст части для каждого шаблона, определив подходящие типы содержимого и порядок, и вернёт полностью подготовленный объект Mail::Message, для отправки которого достаточно вызвать :deliver.
Например:
class Notifier < ActionMailer::Base
default from: 'no-reply@test.lindsaar.net'
def welcome
mail(to: 'mikel@test.lindsaar.net')
end
end
Метод выполнит поиск всех шаблонов с именем «welcome» в каталоге «app/views/notifier». Если шаблон welcome не найден, будет вызвана ошибка ActionView::MissingTemplate.
Однако эти параметры можно изменить:
mail(template_path: 'notifications', template_name: 'another')
Теперь будут найдены все шаблоны с именем «another» в каталоге «app/views/notifications».
Если передать блок, можно отобразить выбранные шаблоны:
mail(to: 'mikel@test.lindsaar.net') do |format| format.text format.html end
Можно даже вывести обычный текст напрямую, не используя шаблон:
mail(to: 'mikel@test.lindsaar.net') do |format|
format.text { render plain: "Hello Mikel!" }
format.html { render html: "<h1>Hello Mikel!</h1>".html_safe }
end
В результате будет сформировано письмо типа multipart/alternative с частями text/plain и text/html.
Синтаксис с блоком также позволяет при необходимости настраивать заголовки частей:
mail(to: 'mikel@test.lindsaar.net') do |format| format.text(content_transfer_encoding: "base64") format.html end
# File actionmailer/lib/action_mailer/base.rb, line 673 def mailer_name self.class.mailer_name end
Возвращает имя объекта почтового отправителя.
Закрытые методы экземпляра
# File actionmailer/lib/action_mailer/base.rb, line 932
def default_i18n_subject(interpolations = {}) # :doc:
mailer_scope = self.class.mailer_name.tr("/", ".")
I18n.t(:subject, **interpolations, scope: [mailer_scope, action_name], default: action_name.humanize)
end Переводит subject с помощью класса Rails I18n в области [mailer_scope, action_name]. Если перевод subject в указанной области не найден, используется человекочитаемый вариант action_name. Если тема содержит интерполяции, их можно передать через параметр interpolations.
# File actionmailer/lib/action_mailer/base.rb, line 910
def set_content_type(m, user_content_type, class_default) # :doc:
params = m.content_type_parameters || {}
case
when user_content_type.present?
user_content_type
when m.has_attachments?
if m.attachments.all?(&:inline?)
["multipart", "related", params]
else
["multipart", "mixed", params]
end
when m.multipart?
["multipart", "alternative", params]
else
m.content_type || class_default
end
end Используется методом mail для установки типа содержимого сообщения.
Используется заданный user_content_type либо multipart, если у письма есть вложения. Если вложения встроенные, тип содержимого будет «multipart/related», в противном случае — «multipart/mixed».
Если тип содержимого не передан в заголовках и вложений нет либо сообщение является составным, используется тип содержимого по умолчанию.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.