Action Mailer

Introduction

Email Configuration


# In environment.rb or in config/environments/*. Defaults to :smtp
config.action_mailer.delivery_method = :test|:smtp|:sendmail
# Authentication is one of :plain, :login, and :cram_md5
ActionMailer::Base.smtp_settings = {
  :address => "mail.messagingengine.com",
  :port => 25,
  :domain => "mail.messagingengine.com",
  :authentication => :login,
  :user_name => "peter_marklund@fastmail.fm",
  :password => "..." 
}
config.action_mailer.perform_deliveries = true | false
config.action_mailer.default_charset = "iso-8859-1" 

Creating a Mailer Class


# Creates app/models/statistics_mailer.rb
script/generate mailer StatisticsMailer

The Mailer Class


class StatisticsMailer < ActionMailer::Base
  def monthly(user, stats, sent_on = Time.now)
    subject       "Monthly statistics" 
    body {:user => user, :stats => stats}
    recipients   user.email
    from         'admin@somecompany.com'
    sent_on      sent_on
    headers      {}
    bcc          'peter_marklund@fastmail.fm'
    content_type "text/html" 
  end
end

The Mailer Template


# In app/views/statistics_mailer/monthly.rhtml
Dear <%= @user.name %>,
here is the statistics for <%= 1.month.ago.strftime("%B") %>.

<%- for service in @user.customer.services -%>
*** Service <%= service.name %>
  Number of calls: <%= @stats[service.id]['n_calls'] %>
  ...
<%- end -%>

Regards

Peter Marklund

Mailer Layouts


# As of Rails 2.2 you can use layouts for your mailers just as you would for
# controllers, so for the StatisticsMailer we can put our layout in:
app/views/layouts/statistics_mailer.html.erb

Sending Email


StatisticsMailer.deliver_monthly(user, stats)

# Alternatively, you can do:
email = StatisticsMailer.create_monthly(user, stats) #=> TMail::Mail object
# Set any properties on the email here
email.set_content_type("text/html")
StatisticsMailer.deliver(email)

Multipart Emails


# Approach 1: One template per content type: monthly.text.plain.erb, monthly.text.html.erb etc.

# Approach 2: Using the part method:
def signup_notification(recipient)
  # recipients, subject, from etc. here...
  part :content_type => "text/html",
    :body => render_message("signup-as-html", :account => recipient)
  part "text/plain" do |p|
    p.body = render_message("signup-as-plain", :account => recipient)
    p.transfer_encoding = "base64" 
 end
end

Attachments


def signup_notification(recipient)
   recipients      recipient.email_address_with_name
   subject         "New account information" 
   from            "system@example.com" 

   attachment :content_type => "image/jpeg",
     :body => File.read("an-image.jpg")

   attachment "application/pdf" do |a|
     a.body = generate_your_pdf_here()
   end
end

Receiving Email


class BulkReceiver < ActionMailer::Base
  def receive(email)
    # Process received email here
  end
end
# Configure your mail server to pipe incoming email to the program
/path/to/app/script/runner 'BulkReceiver.receive(STDIN.read)'

Unit Testing Mailers


user = users(:peter)
email = UserMailer.create_signup_notification(user)
assert_match /you have been signed up/i, email.subject
assert email.body.include?(my_account_url(user))
assert_equal user.email, email.to
assert_equal "admin@mysite.com", email.from