Class: Merb::MailController

Sending mail from a controller involves three steps:

First, create a file in app/mailers that subclasses Merb::MailController. The actions in this controller will do nothing but render mail.

  # app/mailers/article_mailer.rb
  class ArticleMailer < Merb::MailController

    def notify
      @user = params[:user]
      render_mail
    end

  end

You also can access the params hash for values passed with the Controller.send_mail method. See also the documentation for render_mail to see all the ways it can be called.

Create a template in a subdirectory of app/mailers/views that corresponds to the controller and action name. Put plain text and ERB tags here:

  # app/mailers/views/article_mailer/notify.text.erb
  Hey, <%= @user.name %>,

  We're running a sale on dog bones!

Finally, call the Controller.send_mail method from a standard Merb controller.

  class Articles < Application

    def index
      @user = User.find_by_name('louie')

      send_mail(ArticleMailer, :notify, {
        :from => "me@example.com",
        :to => "louie@example.com",
        :subject => "Sale on Dog Bones!"
      }, { :user => @user })
      render
    end

  end

Note: If you don‘t pass a fourth argument to Controller.send_mail, the controller‘s params will be sent to the MailController subclass as params. However, you can explicitly send a hash of objects that will populate the params hash instead. In either case, you must set instance variables in the MailController‘s actions if you want to use them in the MailController‘s views.

The MailController class is very powerful. You can:

  • Send multipart email with a single call to render_mail.
  • Attach files.
  • Render layouts and other templates.
  • Use any template engine supported by Merb.

Attributes

NameRead/write?
base_controller R
mail RW
mailer RW
params RW
session R

Public Class Methods


dispatch_and_deliver (method, mail_params, send_params = {})

A convenience method that creates a blank copy of the MailController and runs dispatch_and_deliver on it.

     # File lib/merb/mail_controller.rb, line 248
248:     def self.dispatch_and_deliver(method, mail_params, send_params = {})
249:       new(send_params).dispatch_and_deliver method, mail_params
250:     end

new (params = {}, controller = nil)

You can initialize a MailController with a series of parameters that can be used by methods in the class. You can also pass in a controller object, which will be available to the MailController methods as base_controller.

    # File lib/merb/mail_controller.rb, line 80
80:     def initialize(params = {}, controller = nil)
81:       @params = params
82:       @base_controller = controller
83:       @session = (controller && controller.session) || {}
84:       super
85:     end

Public Instance Methods


attach ( file_or_files, filename = file_or_files.is_a?(File) ? File.basename(file_or_files.path) : nil, type = nil, headers = nil)

Attaches a file or multiple files to an email. You call this from a method in your MailController (including a before filter).

  attach File.open("foo")
  attach [File.open("foo"), File.open("bar")]

You can also include the filename, mime-type, or headers in the subsequent parameters.

If you are passing an array of files, you should use an array of the allowed parameters:

  attach [[File.open("foo"), "bar", "text/html"], [File.open("baz"),

"bat", "text/css"]

 which would attach two files ("foo" and "baz" in the filesystem) as

"bar" and "bat" respectively. It would also set the mime-type as "text/html" and "text/css" respectively.

     # File lib/merb/mail_controller.rb, line 213
213:     def attach( file_or_files, filename = file_or_files.is_a?(File) ? File.basename(file_or_files.path) : nil, 
214:       type = nil, headers = nil)
215:       @mail.attach(file_or_files, filename, type, headers)
216:     end

dispatch_and_deliver (method, mail_params)

take a method name to dispatch to and mail parameters for the MailFactory object.

Available mail parameters include:

  to
  from
  replyto
  subject
  body
  cc

Other parameters passed in will be interpreted as email headers, with _‘s converted to -’s.

     # File lib/merb/mail_controller.rb, line 230
230:     def dispatch_and_deliver(method, mail_params)
231:       @mailer         = self.class._mailer_klass.new(mail_params)
232:       @mail           = @mailer.mail
233:       @method         = method
234:       
235:       # dipatch and render use params[:action], so set it
236:       params[:action] = method
237:       body            = dispatch method
238:       if !@mail.html.blank? || !@mail.text.blank? 
239:         @mailer.deliver!
240:         Merb.logger.info "#{method} sent to #{@mail.to} about #{@mail.subject}"
241:       else
242:         Merb.logger.info "#{method} was not sent because nothing was rendered for it"
243:       end
244:     end

filters_halted ()

    # File lib/merb/mail_controller.rb, line 87
87:     def filters_halted
88:     end

render_mail (options = @method)

Allows you to render various types of things into the text and HTML parts of an email If you include just text, the email will be sent as plain-text. If you include HTML, the email will be sent as a multi-part email.

There are a lot of ways to use render_mail, but it works similarly to the default Merb render method.

First of all, you‘ll need to store email files in your app/mailers/views directory. They should be under a directory that matches the name of your mailer (e.g. TestMailer‘s views would be stored under test_mailer).

The files themselves should be named action_name.mime_type.extension. For example, an erb template that should be the HTML part of the email, and rendered from the "foo" action would be named foo.html.erb.

The only mime-types currently supported are "html" and "text", which correspond to text/html and text/plain respectively. All template systems supported by your app are available to MailController, and the extensions are the same as they are throughout the rest of Merb.

render_mail can take any of the following option patterns:

  render_mail

will attempt to render the current action. If the current action is "foo", this is identical to render_mail :foo.

  render_mail :foo

checks for foo.html.ext and foo.text.ext and applies them as appropriate.

  render_mail :action => {:html => :foo, :text => :bar}

checks for foo.html.ext and bar.text.ext in the view directory of the current controller and adds them to the mail object if found

  render_mail :template => {:html => "foo/bar", :text => "foo/baz"}

checks for bar.html.ext and baz.text.ext in the foo directory and adds them to the mail object if found.

  render_mail :html => :foo, :text => :bar

the same as render_mail :action => {html => :foo, :text => :bar }

  render_mail :html => "FOO", :text => "BAR"

adds the text "FOO" as the html part of the email and the text "BAR" as the text part of the email. The difference between the last two examples is that symbols represent actions to render, while string represent the literal text to render. Note that you can use regular render methods instead of literal strings here, like:

  render_mail :html => render(:action => :foo)

but you‘re probably better off just using render_mail :action at that point.

You can also mix and match:

  render_mail :action => {:html => :foo}, :text => "BAR"

which would be identical to:

  render_mail :html => :foo, :text => "BAR"
     # File lib/merb/mail_controller.rb, line 157
157:     def render_mail(options = @method)
158:       @_missing_templates = false # used to make sure that at least one template was found
159:       # # If the options are not a hash, normalize to an action hash
160:       options = {:action => {:html => options, :text => options}} if !options.is_a?(Hash)
161:       
162:       # Take care of the options
163:       use_options = {}
164:       opts = options.dup
165:       actions = opts.delete(:action) if opts[:action].is_a?(Hash)
166:       templates = opts.delete(:template) if opts[:template].is_a?(Hash)
167:       
168:       # Prepare the options hash for each format
169:       # We need to delete anything relating to the other format here
170:       # before we try to render the template.
171:       [:html, :text].each do |fmt|
172:         opts_hash = use_options[fmt] = {}
173:         opts_hash[fmt] = opts.delete(fmt)
174:         opts_hash[fmt] ||= actions[fmt] if actions && actions[fmt]
175:         opts_hash[:tempalte] = templates[fmt] if templates && templates[fmt]
176:       end
177:       
178:       # Send the result to the mailer
179:       { :html => "rawhtml=", :text => "text="}.each do |fmt,meth|
180:         begin
181:           value = render use_options[fmt].merge!(opts).merge!(:clean_context => true, :format => fmt)
182:           @mail.send(meth,value) unless value.nil? || value.empty?
183:         rescue => e
184:           # An error should be logged if no template is found instead of an error raised
185:           if @_missing_templates
186:             Merb.logger.error(e)
187:           else
188:             @_missing_templates = true
189:           end
190:         end
191:       end
192:       @mail
193:     end

Protected Instance Methods


route ()

     # File lib/merb/mail_controller.rb, line 253
253:     def route
254:       @base_controller.route if @base_controller
255:     end