1
votes

We have a Rails 3.2.14 app that is misbehaving in production only. Emails fail to send with the following error message:

ActionView::MissingTemplate (Missing template /invoice with {:locale=>[:en], :formats=>[:text], :handlers=>[:erb, :builder]}. Searched in:
  * "/var/www/appname/releases/20131003214241/app/views"
):
app/mailers/mailer.rb:42:in `block in invoice'
app/mailers/mailer.rb:41:in `invoice'
app/controllers/admin_controller.rb:410:in `resend_invoice'

The Mailer#invoice method looks like this:

def invoice(order, resent=false, receipt_or_invoice = "Receipt")
  @order = order
  @freebie = @order.freebie?
  @mail = true
  @transaction = @order.beanstream_transaction
  @user = @order.user
  recipient = @order.email_receipt_to || @user.email || "[email protected]"
  @receipt_or_invoice = receipt_or_invoice

  subject = @freebie ? "Your License" : "Your #{receipt_or_invoice.capitalize} and License     Information#{ resent ? " (Resent)" : ""}"
  mail = mail(:to => [recipient], :subject => subject)
  mail.add_part(Mail::Part.new do
    content_type 'multipart/alternative'
    # THE ODD BIT vv
    mail.parts.reverse!.delete_if {|p| add_part p }
  end)
  mail.content_type 'multipart/mixed'
  mail.header['content-type'].parameters[:boundary] = mail.body.boundary
  @order.line_items.each do |li|
    aq_data = li.license.aquatic_prime_data
    if aq_data.present?
      attachments[li.license.aquatic_prime_filename] = {content: aq_data, mime_type:     'application/xml'}
    end
  end
  return mail
end

A couple notes.

  1. This behaves fine in development using Pow. Production is using Apache+Passenger.
  2. Before this, the last change we made to our mailer was in June to add a new method. We've seen no other reports about failure to deliver emails. This makes me think something changed in the ActionMailer or other Rails gem that somehow caused this issue.
  3. The error also happens when Mailer.invoice is called from our store controller or other part of the code, so I think it's localized to the Mailer.
  4. In development, we're using Google SMTP server for sending mail, whereas we're using Postmark in production.

Thanks in advance for any help or insights!

1

1 Answers

1
votes

Turns out, if something seems very complicated, you're usually doing it wrong. I changed our Mailer#invoice method to be like this and it worked fine:

def invoice(order, resent=false, receipt_or_invoice = "Receipt")
  @order = order
  @freebie = @order.freebie?
  @mail = true
  @transaction = @order.beanstream_transaction
  @user = @order.user
  recipient = @order.email_receipt_to || @user.email || "[email protected]"
  @receipt_or_invoice = receipt_or_invoice

  subject = @freebie ? "Your License" : "Your #{receipt_or_invoice.capitalize} and License         Information#{ resent ? " (Resent)" : ""}"
  @order.line_items.each do |li|
    aq_data = li.license.aquatic_prime_data
    if aq_data.present?
      attachments[li.license.aquatic_prime_filename] = {content: aq_data, mime_type:         'application/xml'}
    end
  end
  mail(:to => [recipient], :subject => subject)
end

The key bit is to do the attachments before the mail method. Then the multipart/alternative stuff works fine and the attachments are handled properly.

We still had a problem with Postmark refusing to deliver our custom file extension attachment, but that's a separate issue. I don't know why all the machinations we were going through were gumming up our view template_path or why the problem wasn't manifesting in development, but there it is…