Creating a Custom Mailer Class with the Mailer Generator

Problem

Contributed by: Dae San Hwang

You've configured Rails to talk to a mail server, but you still don't have a way to generate and send the messages themselves. You want to create a custom mailer class to send out emails.

For example, you have a web site where new customers can register for online accounts. You want your application to send a welcoming email to every new customer who registers.

Solution

From your application's root directory, use the mailer generator to create a new CustomMailer class.

$ ruby script/generate mailer CustomerMailer welcome_message
 exists app/models/
 create app/views/customer_mailer
 exists test/unit/
 create test/fixtures/customer_mailer
 create app/models/customer_mailer.rb
 create test/unit/customer_mailer_test.rb
 create app/views/customer_mailer/welcome_message.rhtml
 create test/fixtures/customer_mailer/welcome_message

CustomerMailer is the name of your new mailer class, and welcome_message is the name of the constructor method used to create email messages. The mailer generator creates scaffolding for the welcome_message method in the app/model/customer_mailer.rb file.

app/model/customer_mailer.rb:

class CustomerMailer < ActionMailer::Base
 def welcome_message(sent_at = Time.now)
 @subject = 'CustomerMailer#welcome_message'
 @body = {}
 @recipients = ''
 @from = ''
 @sent_on = sent_at
 @headers = {}
 end end

You then customize the welcome_message method in CustomerMailer to suit your purpose. In the following example, the welcome_message method takes the customer's name and email address as arguments, and composes a complete email message:

app/model/customer_mailer.rb:

class CustomerMailer < ActionMailer::Base
 def welcome_message(cust_name, cust_email)
 @subject = "Welcome to Our Site"
 @body = "Welcome #{cust_name},\n\n"
 + "Thank you for registering!\n\n"
 + "Use your email address (#{cust_email}) and password to log in."
 @recipients = cust_email
 @from = "webmaster@yourwebsite.com"
 @sent_on = Time.now
 end end

Discussion

While the names of the instance variables in the welcome_message method pretty clearly indicate their purpose, note that @recipients is plural. If there is only one recipient for the email message, @recipients is assigned a String containing a single email address. However, if there is more than one recipient, @recipients will contain an array of String objects, each containing a single email address.

The instance methods defined in the CustomerMailer class are never called directly. Instead, prepend a create_ prefix to the name of the instance method you wish to call, and call that instead (e.g., instead of calling CustomerMailer.welcome_message, you call CustomerMailer.create_welcome_message). The welcome_message method is then called implicitly with the arguments you pass to create_welcome_message, creating a new TMail object. This newly created object is returned to the caller of create_welcome_message.

In fact, the class methods with the create_ prefix are never defined. Instead, Action Mailer uses Ruby's method_missing function to dynamically handle these method calls as if the class methods existed.

The mailer class files are saved in the same directory as the Active Record model class files. Therefore, always use the Mailer suffix when creating a new mailer class to keep from confusing them with Active Record model classes.

See Also