4
votes

I'm trying to figure out if it's possible using ActionMailer without Rails to render an html.erb view once and then send that out multiple times just using different emails in :to?

NOTE: I'm NOT using the full Rails stack, just ActionMailer

So in the mailer class

class MyMailer < ActionMailer::Base
  default :from     => '[email protected]',
          :subject  => 'New Arrivals!'

  def new_products(customer, new_products)
    @new_products = new_products

    mail :to => customer.email do |format|
        format.html
    end
  end
end

Then, in the client code, we need to get the new products and the customers.

products = Product.new_since_yesterday
customers = Customer.all

customers.each do |c|
  MyMailer.new_products(c, products).deliver
end

Let's say this is sent out once per day, so we only want to get the new products since the last time we sent the email. We only want to render this once since the new products for today won't change between emails. As far as I know, this will call render each time an email is created and sent.

Is there a way to tell ActionMailer to only render this once and then somehow reference the object that contains the rendered view. This would cut out all the time it takes for render to do it's thing. The email addresses being sent to would change, but the content of the email will not.

Obviously for lots of emails you would not simply loop through a list and create/deliver email. You might use a queue for that. In general though, when it's unnecessary to produce the render step multiple times, how would you do it once and use that result for all of the emails?

Potentially my unfamiliarity with ActionMailer is failing me here.

1

1 Answers

2
votes

I haven't tried this, but a call to a mailer just returns a plain old Mail::Message object, complete with a body. So you should be able to just grab the body and reuse it.

message = MyMailer.new_products(c, products)
message_body = message.body

customers.each do |c|
  mail = Mail.new do
    from    '[email protected]'
    to      c.email
    subject 'this is an email'
    body    message_body
  end
  mail.deliver
end

You might even be able to get more 'efficient' by duping the message

message = MyMailer.new_products(c, products)

customers.each do |c|
  mail = message.dupe()
  mail.to = c.email
  mail.deliver
end