Rails in a nutshell Chapter 5. Action Mailer
Translations of this material:
- into Russian: Перевод "Rails in a nutshell Chapter 5. Action Mailer". 16% translated in draft.
-
Submitted for translation by minibikini 20.10.2010
Text
Chapter 5. Action Mailer
Action Mailer is a framework for sending and receiving email. It makes sending templated email, gracefully degrading HTML email, email with attachments, and receiving email simple, while abstracting away complex issues like MIME encoding and quoting. This chapter will cover all the most important aspects of Action Mailer including the generation of mailers, sending email, and the configuration and testing of mailers.
Generating Mailers
Rails provides a generator for creating new mailer models. The generator is passed the mailer name in underscored or camel case format followed by zero or more actions:
script/generate mailer mailer_name [action...]
The generator creates the following files:
*
mailer class in app/models.
*
view templates for each action in app/views/mailer_name.
*
unit test stub in test/unit.
*
test fixtures for each action in test/fixtures/mailer_name.
The following command generates a new mailer model class named OrderMailer with a single action confirmation:
$ script/generate mailer OrderMailer confirmation
create app/models/
create app/views/order_mailer
create test/unit/
create test/fixtures/order_mailer
create app/models/order_mailer.rb
create test/unit/order_mailer_test.rb
create app/views/order_mailer/confirmation.erb
create test/fixtures/order_mailer/confirmation
Sending Email
A mailer model's job is to encapsulate the creation and delivery of the different email messages that you need for a particular component of your application. For example, an OrderMailer would define all of the email messages for communicating with a customer regarding an order they've placed at your online store.
There are two parts to a mailer: the model and the view. The model portion is stored along with the rest of your models in app/models. The mailer's views are stored in a subdirectory, named after the mailer model, underneath app/views with the rest of your application's views. Therefore an OrderMailer model would itself be stored as app/models/order_mailer.rb and would look for its view templates under the directory app/views/order_mailer.
Mailer Models
Mailer models define any number of different email messages through what are called mailer actions. Each mailer action is simply an instance method defined in the mailer class. The method body of the action is where you configure the properties and options for the email and prepare the variables that will be passed to the view template for rendering. Following is the definition of an order confirmation email:
Example 5.1. A basic mailer model
class OrderMailer < ActionMailer::Base
def confirmation(order)
recipients order.email
from "order-confirm@snowdevil.ca"
subject "Your order with Snowdevil"
body :order => order
end
end
This mailer has a single action confirmation that has a single parameter order. The order is an instance of the customer's order. The action sets the attributes that control the content of the created email message, who the message will appear to be from, and who will receive the message.
Note
Action Mailer model attributes are defined with a macro that is similar to Ruby's attr_accessor called adv_attr_accessor. adv_attr_accessor works the same way as attr_accessor, but an additional setter method is created that allows you to set an instance variable by calling the defined method name with an argument. Both of the following lines of code set the @from instance variable:
@from = "nutshell@example.com"
from "nutshell@example.com"
Setting the attribute through the method call, as shown in the second line above, is the preferred way of setting mailer attributes. This style tends to produce more natural, aesthetically pleasing mailers and is therefore the style used throughout this chapter, the Rails documentation, and mailer generators.
Let's take a closer look at the most important and commonly used mailer attributes. The following attributes control the content of the email message:
subject
The subject of the email. Sets the Subject email header.
body
The email body. Can be set to either a string or a hash. If the body is set to a string then the string will be used as the email body. If the body is set to a hash then the action's view template will have instance variables set for each key-value pair in the hash. This will be covered in more detail in the section called “Mailer Views”.
These attributes control who will receive the email and who the email will be sent from:
recipients
The addresses the email will be delivered to. Can be a single email address or an array of email addresses. Sets the To email header.
cc
The carbon copy recipients of the email. Can be a single email address or an array of email addresses. Sets the Cc email header.
bcc
The blind carbon copy recipients of the email. Can be a single email address or an array of email addresses. Sets the Bcc email header.
from
The email address the email will be sent from. Sets the From email header.
Note
Email addresses can be provided in any format that is compliant with the RFC 2822 Address Specification. RFC 2822 addresses take the general form:
"Full Name or Phrase" <username@host> (Comment Area)
Some valid RFC 2822 email addresses:
david@host.example.com
David Hansson <david@host.example.com>
David Hansson <david@host.example.com> (Creator of Rails)
Mailer Views
View templates can be rendered using any template handler registered with Rails such as ERb, Builder, or even a custom handler such as Haml. For more information on template handlers see ???.
To automatically render the email body from a view template you need to:
*
Create a view template in the mailer's views directory with the same name as the mailer action.
*
Give the template the file extension of the template handler you want to use to render the view with such as .erb or .builder.
*
Set the content_type attribute in the mailer action unless you're sending plain text. The content-type defaults to text/plain.
Note
It is possible to manually render the email body using the private mailer method render_message:
body render_message("confirmation")
Manually rendering the template is only necessary if you need to render a template with a name that doesn't match the mailer action.
Then you assign the body attribute to a hash containing any variables you want assigned as instance variables in the view. An instance variable is created in the view for each key in the hash with the name of the key and the value of the key's corresponding value.
Note
Strings or symbols are interchangeable as keys in hash passed to the view. For example, the keys :title and "title" will both result in the assignment of an instance variable @title in the view.
The mailer renders a simple ERb view template. For more information about rendering ERb templates see ???. Let's take a look a the template for the order confirmation email: app/views/order_mailer/notification.erb:
Thank you for your purchase. You ordered the following items:
<% @order.line_items.each do |item| -%>
<%= item.description %> - <%= number_to_currency(item.price) %>
<% end -%>
