Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Attempt to send an email via Rails ActionMailer results in a failed call to `normalize_name` inside `lookup_context.rb`

I have a Mailer class which inherits from ApplicationMailer, which in turn inherits from ActionMailer::Base. Ruby version is ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin15].

The Mailer class looks like the following:

class PurchaseOrderStatusMailer < ApplicationMailer
  CONTACTS = {
    JC: ['[email protected]'],
    RM: ['[email protected]']
  }

  def daily_report_email(facility)
    @facility = facility
    ingredient_items = LineItem.ingredient.by_facility(facility)
    @delivered_count = ingredient_items.by_date([7.days.ago, 7.days.from_now]).delivered.count
    @partial_count = ingredient_items.by_date([7.days.ago, 1.day.ago]).partial.count
    @late_count = ingredient_items.by_date([7.days.ago, 1.day.ago]).late.count
    @expected_count = ingredient_items.by_date([Date.today, 7.days.from_now]).expected.count
    mail(to: CONTACTS[facility.to_sym], subject: "#{facility} Daily Receipt Status - #{Date.today}")
  end
end

ApplicationMailer looks like the following:

# frozen_string_literal: true
class ApplicationMailer < ActionMailer::Base
  default from: '[email protected]'

  def facility_email(facility)
    emails = Rails.application.config_for(:emails)
    (emails[facility] + emails["DEFAULT"]).flatten
  end
end

The view is located at app/views/purchase_order_status_mailer/daily_report_email.html.erb.

When I open my Rails console and type PurchaseOrderStatusMailer.new.daily_report_email('JC').deliver, I see the following error:

NoMethodError: undefined method `empty?' for nil:NilClass
from /Users/me/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/actionview-5.0.4/lib/action_view/lookup_context.rb:215:in `normalize_name'

I tried passing a format block to the call to the mail helper with the same call, like so:

mail(to: CONTACTS[facility.to_sym], subject: "#{facility} Daily Receipt Status - #{Date.today}") do |format|
  format.text { render plain: "Hey!" }
end

The above produced the following response, which appears to represent a successful email send:

  Rendering text template
  Rendered text template (0.0ms)
Sent mail to [email protected] (8.8ms)
Date: Mon, 25 Sep 2017 12:55:11 -0400
From: [email protected]
To: [email protected]
Message-ID: <[email protected]>
Subject: JC Daily Receipt Status - 2017-09-25
Mime-Version: 1.0
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

Hey!
=> #<Mail::Message:70191029273300, Multipart: false, Headers: <Date: Mon, 25 Sep 2017 12:55:11 -0400>, <From: [email protected]>, <To: ["[email protected]"]>, <Message-ID: <[email protected]>>, <Subject: JC Daily Receipt Status - 2017-09-25>, <Mime-Version: 1.0>, <Content-Type: text/plain>, <Content-Transfer-Encoding: 7bit>>

I didn't actually receive an email, and I assume that means I don't have SMTP set up on my local machine, but the above response is encouraging. There was no stack trace apart from the error I posted above, so I tried digging into the Rails source code, and I saw that normalize_name inside lookup_context.rb gets called from within the args_for_lookup protected method, which in turn gets called by the ViewPaths module's find_all method. But beyond that it was hard to trace the call stack, as I couldn't find who the caller of find_all is.

My question is: what is wrong with the first call to mail?

EDIT 1: I also tried format.html { render html: "<h1>Hello Mikel!</h1>".html_safe } instead of the format.text option, as per the example here, and I got a similar success message.

I then tried adding a byebug statement inside normalize_name, to try and identify what the values of the parameters were on the successful email sends, but it looks like this method isn't getting called when a block is passed. That makes me suspect even more strongly that the problem is somehow related to my views. But I can't confirm that yet.

like image 380
Richie Thomas Avatar asked Sep 25 '17 17:09

Richie Thomas


People also ask

What is ActionMailer?

1 Introduction. Action Mailer allows you to send emails from your application using a mailer model and views. So, in Rails, emails are used by creating mailers that inherit from ActionMailer::Base and live in app/mailers. Those mailers have associated views that appear alongside controller views in app/views.


2 Answers

The issue is here

PurchaseOrderStatusMailer.new.daily_report_email('JC').deliver

remove the new i.e

PurchaseOrderStatusMailer.daily_report_email('JC').deliver

Because of the wrong object of its not able to deduce the template path/file

like image 58
sethi Avatar answered Sep 18 '22 12:09

sethi


I was able to generate a success response (including my mailer's rendered template file) by passing template_path and template_name options to the original call to the mail helper, like so:

mail(
  to: CONTACTS[facility.to_sym],
  subject: "#{facility} Daily Receipt Status - #{Date.today}",
  template_path: 'purchase_order_status_mailer',
  template_name: 'daily_report_email')

This generated the following success response:

  Rendering purchase_order_status_mailer/daily_report_email.text.erb
  Rendered purchase_order_status_mailer/daily_report_email.text.erb (0.3ms)
Sent mail to [email protected] (12.1ms)
Date: Mon, 25 Sep 2017 15:18:25 -0400
From: [email protected]
To: [email protected]
Message-ID: <[email protected]>
Subject: JC Daily Receipt Status - 2017-09-25
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_59c9568120033_11e943fee8503f8282341e";
 charset=UTF-8
Content-Transfer-Encoding: 7bit


----==_mimepart_59c9568120033_11e943fee8503f8282341e
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

Please find the receipt status for JC as of 09-25-2017:
=================================================================================================

...<lots more content, including ERB rendered into HTML>...

=> #<Mail::Message:70293683934580, Multipart: true, Headers: <Date: Mon, 25 Sep 2017 15:18:25 -0400>, <From: [email protected]>, <To: ["[email protected]"]>, <Message-ID: <[email protected]>>, <Subject: JC Daily Receipt Status - 2017-09-25>, <Mime-Version: 1.0>, <Content-Type: multipart/alternative; boundary="--==_mimepart_59c9568120033_11e943fee8503f8282341e"; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>

I'm a little confused about why I had to add these options, as the documentation doesn't make it clear that these are required and my templates and folders appear to be named correctly, but it worked and I have deadlines so I'm moving on. :-)

like image 33
Richie Thomas Avatar answered Sep 20 '22 12:09

Richie Thomas