Intermittent Rails mailer 'missing template' issue - ruby-on-rails

I say intermittent, but it's really like 50% of the time. Here's what I'm using:
Rails 4.2.1
Sidekiq 3.4.1
I have a mailer that runs from ActiveJob, and half the time it is unable to find its associated template:
Missing template notifier/claim_email with "mailer". Searched in:
* "notifier"
The template is most definitely present and named properly:
$ ls app/views/notifier/
claim_email.html.erb
claim_email.txt.erb
Code:
def claim_email(subject, message)
#message = message
mail(
to: %Q{<#{ENV['DEFAULT_EMAIL']}>},
subject: subject,
)
end
Template:
<%= #message %>
I've also tried adding the :body option to send directly, but it inexplicably still tries to use the template(?!) I've restarted the app multiple times to no avail. This also always works in development. I'm baffled as to what could be happening here.

I figured it out. I was having the same issue as the person in this question:
Rails.root points to the wrong directory in production during a Resque job
My sidekiq jobs were not being properly restarted on deploy, which led them to have old pathnames for templates.

I had the same issue. Restarting sidekiq solved it for me. Good luck!

Related

Sidekiq / active job not sending e-mails in production

When I try to send e-mails with Sidekiq (5.1.3) and Rails (5.1.6) in production using ActiveJob's deliver_later, e-mails are not being sent (deliver_now works fine). The job gets processed and Sidekiq reports it as such. The logs show a successful start & done:
2018-09-14T14:12:18.031Z 14029 TID-mncgx ActionMailer::DeliveryJob JID-665575b056e61ef84a434c97 INFO: done: 0.84 sec
The only thing missing is the delivery of the actual e-mail. I've enabled 'raise_delivery_errors', but nothing is being raised. I'm sending my email through Mailgun.
I'm inclined to think something's going wrong with Sidekiq, because I had ActiveJob configured before (with the default adapter, :async) and deliver_later worked properly. Only after adding Sidekiq it stopped working. I've tried it with many different e-mails and in the end I created an extremely simple mailer, just for debugging this issue.
Here's the code of my 'job':
SimpleMailer.test.deliver_later
And here's the code of my mailer:
class SimpleMailer < ApplicationMailer
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.simple_mailer.test.subject
#
def test
#greeting = "Hi"
mail to: xx, from: xx, subject: 'Well hello"
end
Thanks a lot in advance! I've been searching for quite some time now and have lost almost all inspiration - any help (on where to look) would be amazing. I could also provide more info, but I don't really know what's more to provide.

Sidekiq Delayed Mailer does not use updated mailer views after deploy

My production system is using Sidekiq's delayed mailer extension to send automated mails through Mailgun's smtp server.
All is well except there is a particular mail that when opened in its text alternative it uses the view from the previous deploy (while the html version is renders correctly).
Up to now I have restarted unicorn + sidekiq multiple times, I have created a new commit and deployed again while rewriting the whole view just in case but nothing works.
The production server is using unicorn, sidekiq connects to a redis instance on the same machine, while actionmailer is using the Mailgun SMTP. The mailer method is the following :
def new_shipment_added(shipment_id, user_id)
#shipment = Shipment.find(shipment_id)
#user = User.find(user_id)
return false if #shipment.nil? or #user.nil?
rcpts = Array.new
#user.email_addresses.each { |addrObj| rcpts << addrObj.address}
m = mail(to: rcpts, subject: t("subject_line_with_title", title: "#{#shipment.pickup.compact_address} - #{#shipment.delivery.compact_address}"))
end
I am including the method for context but I think that it's not causing the problem since html templates render correctly.
The bottom line of the question is : What could be causing the problem? ..and also how is sidekiq using the older template, since it can only be found in previous releases?

uninitialized constant - loading class issue?

So, I got mailer app/mailers/dynamic_mailer.rb and model app/models/email_message/outgoing.rb. There is method:
class EmailMessage::Outgoing < EmailMessage
...
def deliver_mail
l = ::DynamicMailer.email_message(self).deliver!
Rails.logger.info "SEND MAIL: #{l.inspect}"
update_attribute(:received_at, Time.now)
end
Locally (developement env) everything works fine. The problem occurs when I'm deploying app to server (staging env) and trying to send email form there. Delayed job prints:
[Worker(host:rdev pid:2279)] EmailMessage::Outgoing#send_email!
failed with NameError: uninitialized constant
EmailMessage::Outgoing::DynamicMailer - 11 failed attempts
It looks like a problem with loading classes on server. Removing double colons before class name fails.
Any help will be greatly appreciated.
Try to specify file with DynamicMailer obviously in file with your model like this require 'app/mailers/dynamic_mailer.rb'. Probably it can help to find necessary class.
Also I've noticed that in error message is mentioned send_email! method but you posted here def deliver_mail method. Whether I don't understand something or you're looking in wrong place.
I just forgot to restart delayed job daemon.
You can do it with capistrano, by adding gem 'daemons' to your Gemfile and updating receipes like that: http://cmar.me/2011/02/21/delayed_job-with-rails-3-and-capistrano/

Rails full error page not showing for view errors

I have a view named new.html.erb with the following code:
<%= some_non_existent_thing.imaginary_method %>
Now, I only see one simple 500 error page, like that:
500 Internal Server Error
If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
Shouldn't I see a pretty formatted page with some information about the exception?
I'm not sure I miss something here, but I believe rails used to show the full error page in development environment when there is something wrong in the view.
Are you sure that you are running the development environment? Check that RAILS_ENV=development or that you are running rails server -e development.
Then check your development.rb file, you should have the following line in it
config.consider_all_requests_local = true
If you happen to have an exception inside an exception, Rails has a middleware that catches it and returns a FAILSAFE_RESPONSE with the following copy:
500 Internal Server Error
If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
A nice way to troubleshoot this is to compare your custom error code with the sample code provided in the Rails 4.2.0 guides.
I'm pointing to that particular version because that whole section was removed in the Rails 5.0.0 guides.
Ideally, you should keep your error views, layout, and controller as free of logic as possible, to avoid running into this issue.
Firstly, as Anton mentions in the answer below, confirm that your config/environments/development.rb has:
config.consider_all_requests_local = true
and that you are running the server in development mode.
I had ensured the above and still observed the error.
This happened in my case, because my logger had some errors. I was using a custom log formatter, which used the String#% method to format the log. % seems to be very buggy and leads to all these weird errors. I figured this one out by adding a debugger line to the controller method and stepping through into the implicit render function call. It hit the bug and reported it as a malformed format string error.
This was the log formatter I was using before, which caused the bugs [I had added it to an initializer file]:
class Logger::SimpleFormatter
def call(severity, time, progname, msg)
"%-7s #{msg}\n" % severity
end
end
These modifications fixed the bug:
class Logger::SimpleFormatter
def call(severity, time, progname, msg)
severity_prefix = "[#{severity}]".ljust(7)
"#{severity_prefix} #{msg}\n"
end
end
This happens if the code is not compilable, for example if you have an if statement missing an end.

Sending emails in test mode with ActionMailer in rails 3

I am having a slightly odd problem with sending mail in test mode with Rails 3
It seems that my mailers are not returning anything. For example I have a mailer called UserMailer. Users can make changes that require approval in the app so this has a method called changes_approved that should send the user an email notifying them that their changes have been approved.class
UserMailer < ActionMailer::Base
default :from => "from#example.com"
def changes_approved(user, page)
#user = user
#page = page
mail(:to => user.email, :subject => "Your changes have been approved")
end
end
In my controller I have the following line
UserMailer.changes_approved(#page_revision.created_by, #page_revision.page).deliver
However my tests fail at this point with the error:
undefined method `deliver' for nil:NilClass
When I trigger the same actions on the development site tho (http://localhost:3000 through a browser), the emails are sent out correctly and everything works quite happily
And to add further confusion, I am using devise for authentication and the emails for that seem to be working correctly both in test and development modes. Certainly I am not getting this same error and according to my email-spec tests, everythings working
So this leads me to believe that I have a problem with my mailers rather than my test mail config per se but I have no idea what. Any suggestions would be much appreciated
Thanks
I used https://gist.github.com/1031144
to convert
# Rails 2 method:
UserMailer.should_receive(:deliver_signup)
to
# Cumbersome Rails 3 method:
mailer = mock
mailer.should_receive(:deliver)
UserMailer.should_receive(:signup).and_return(mailer)
I had a similar problem - probably the UserMailer.changes_approved method is being replaced with a mock method, which returns nil (I wasn't using shoulda for that test, but that's my best guess).
My code looked like this (modified to use your example):
UserMailer.expects(:changes_approved).once
I fixed it with an additional stub:
#mailer = stub(:deliver)
UserMailer.expects(:changes_approved).once.returns(#mailer)
The nil is now replaced with #mailer.
To test the delayed action mailer we need to first change the configuration of delayed_job (in config/initializers/delayed_job_config.rb) to
Delayed::Worker.delay_jobs = !Rails.env.test?
and in your tests the expectation should be set to
mock_mail = mock(:mail)
mock_mail.should_receive(:deliver)
UserMailer.should_receive(:changes_approved).with(user, page).and_return(mock_mail)
Well I have found the answer,
it looks like the problem was in the way I was testing these mailers. In each of the controller tests I had a line similar to
UserMailer.should_receive(:changes_approved).with(user, page)
Whilst this test was passing fine, it appeared to break the mailer itself. I have removed this line from the tests and now they pass ok. Subsequent tests against ActionMailer::Base.deliveries.last to check the details of the sent email are correct appear to be ok so I am happy that this line is not neccessary.
If anyone has an explanation as to why this breaks tho, I would be interested to find out
Thanks anyways

Resources