Note: Using Rails 3.1 and current delayed_job gem.
I have a User model that calls after_create :mail_confirmation.
The mail_confirmation method looks like the following, per the delayed_job instructions:
def mail_confirmation
UserMailer.delay.registration_confirmation(self)
end
The UserMailer is:
class UserMailer < ActionMailer::Base
default from: "test#mysite.com"
def registration_confirmation(user)
#user = user
mail(:to => "#{user.full_name} <#{user.email}>", :subject => "Test registration email")
end
end
The job is queued, and the output from rake jobs:work makes it seem as if it completed successfully:
[Worker(host:mymac.local pid:73694)] Starting job worker
[Worker(host:mymac.local pid:73694)] Class#registration_confirmation completed after 1.3659
[Worker(host:mymac.local pid:73694)] 1 jobs processed at 0.7288 j/s, 0 failed ...
There is no error but the email is never sent. It works fine if I remove delayed from the method call in the User model and go with the standard deliver method:
def mail_confirmation
UserMailer.registration_confirmation(self).deliver
end
How can I find out what is happening when the job is processed? Any idea how to fix it?
Update It appears that it is related to this:
NoMethodError with delayed_job (collectiveidea gem)
Yeah i had this same issue. #Clay is correct, there is an issue at the moment: https://github.com/collectiveidea/delayed_job/issues/323
I resolved this problem by reverting back to the previous version of delayed_job.
gem 'delayed_job', '2.1.2'
I'm having the same issues here. I discovered that for some reason the delay method called on Mailer classes is being handled by the method Delayed::MessageSending#delay instead of Delayed::DelayMail#delay which instantiates the right performable (which is PerformableMailer instead of PerformableMethod). It doesn't crash the job because PerformableMethod just calls the method without the deliver.
Take a look at:
delayted_job/lib/delayed/message_sending.rb
delayted_job/lib/delayed/performable_mailer.rb
Related
I use Postmark for sending email and was looking to capture Postmark::InactiveRecipientError which currently just ends up in my dead jobs in my Sidekiq queue. I found on the postmark-rails wiki, what I thought would be the correct course: https://github.com/wildbit/postmark-rails/wiki/Error-Handling
class ApplicationMailer < ActionMailer::Base
default from: "user#stackoverflow.com"
layout 'mailer'
rescue_from Postmark::InactiveRecipientError, with: :reactivate_and_retry
private
def postmark_client
::Postmark::ApiClient.new(Rails.application.credentials.postmark_api_token)
end
def reactivate_and_retry(error)
error.recipients.each do |recipient|
bounce = postmark_client.bounces(emailFilter: recipient).first
next unless bounce
postmark_client.activate_bounce(bounce[:id])
end
# Try again immediately
message.deliver
end
end
When I test the above in development, everything works. My UserMailer goes to Sidekiq which kicks off and correctly activates a suppressed email which I can see the change made via the Postmark interface. However, in production, my jobs are failing with:
undefined method 'reactivate_and_retry' for class '#<Class:UserMailer>'
I haven't been able to find any resources -- this GitHub Issue seems to be a similar problem but doesn't have much for information -- https://github.com/mperham/sidekiq/issues/4161
I am using Rails 6.1.4.4 and Sidekiq 6.4.0.
I am having the same problem. It seems like nobody has this problem.
The problem is that the job calls handle_exception_with_mailer_class and this doesn't have an instance of mailer so it tries to call a class level method. If you define it as a class method it should work though, or use a lambda/block.
https://github.com/rails/rails/blob/cf82c9d7826aa36f2481114961af02dbf39896dd/actionmailer/lib/action_mailer/delivery_job.rb#L37
Actually I am using the delayed job to run the email process at background. When I called the delay method of delayed_job its insert the record into Delayed::Job table but mails are not going and when I check the delayed_job.log it contains "failed with TypeError: can't convert nil into Hash" error.
UserMailer.rb file contain following code
def welcome_email(user)
#username = user.name
setup_email(user)
end
In User controller
UserMailer.delay.welcome_email(User.last)
But when I removed delay method then mails are going
the code is :
UserMailer.welcome_email(User.last).deliver
I am not getting why this error is coming withe delay,please help me to find the cause of this issue.
Check your mailer configuration.
use this
def welcome_email(user)
##access hash in this way user['email']..not using dot operator user.email
#user=User.find_by_email user['email']
mail(:to => user['email'], :subject => "Hi #{user['username']},Welcome to mywebsite.com")
end
Moreover for delay You need to run the rake jobs:work task to have a process by Delayed Job work off jobs from that table. Without this, you will not receive any emails.
I am using Rails 3.0.9 and I have following code to send an email when a comment is posted.
class Mailer < ActionMailer::Base
def comment_notification(comment)
User.active.each do |user|
#user = user
mail(:to => #user.email, :subject => subject)
end
end
end
If there are not active users then User.active is empty and the code inside does not get executed. However the view is rendered and view fails because #user is missing.
The above code is invoked by observer
Mailer.comment_notification(comment).deliver
One way to fix this problem would be to change the code in observer to something like this
User.active.each do |recipient|
Mailer.comment_notification(comment, recipient).deliver
end
Is this the right way to fix this way. I would like my observer to be as thin as possible.
Yes, your observer fix is correct. You should loop through and send emails one by one. The mailer should just send one email at a time. This is a job best left to Delayed Job though. You don't want to waiting around while an email sends.
Here is a tutorial on Delayed Job: http://railscasts.com/episodes/171-delayed-job
Be sure to check the Readme for Delayed Job as well, paying special attention to the "Rails 3 Mailers" section: http://github.com/collectiveidea/delayed_job
So I'm using Delayed Jobs and I'm trying to figure out how to get all of my mailers to be delayed. Right now, I've put handle_asynchronously on all of my action mailer methods… but I don't think that is going to work.
def first_notification(time)
#time = time
mail :to => time.person.email,
:from => "email#example.com",
:subject => "#{time.person.name} wants to say hi"
end
handle_asynchronously :advisor_first_notification, :priority => 20
The reason I don't think this is going to work is because I call it as such:
UserMailer.first_notification(#time).deliver
So how would it handle the .deliver part of this? Right now I get an exception.
EXCEPTION: #<ArgumentError: wrong number of arguments (1 for 0)>
Which makes me feel that something is getting messed up in the deliver aspect.
I would rather not have a separate job file for each email (as I have a lot of them), so what is the proper way to handle this?
The only other option I can think of is to encapsulate the calls into a method within my models and have them have the handle_asynchronously - that way they can call the entire thing at once.
The mailer is a bit tricky... Instead of using the handle_asynchronously syntax:
UserMailer.delay.first_notification(#time)
The 'trick' is having delay() before the mailer method
Further to Jesse's answer, the collectiveidea's fork of delayed_job indicates that you should definitely not use the deliver method at all with Rails 3 Mailer code:
# without delayed_job
Notifier.signup(#user).deliver
# with delayed_job
Notifier.delay.signup(#user)
I've gotten it to work by doing the following:
class MyMailer < ActionMailer::Base
def send_my_mail_method(*args)
MyMailer.my_mail_method(*args).deliver
end
handle_asynchronously :send_my_mail_method
def my_mail_method(*args)
# mail call ...
end
end
I like this way because it allows me to test that delivery happens interactively, without having to do something stupid like mock the delay call.
I'm using delayed_job 2.1.4 from collectiveidea, and it seems the perform method is never called even though the jobs are processed and removed from the queue. Am I missing something?
I'm using Rails 3.0.5 on Heroku
In the Controller:
Delayed::Job.enqueue FacebookJob.new
In the Job class:
class FacebookJob
def initialize
end
def perform
fb_auths = Authentication.where(:provider => 'facebook')
fb_auths.each do |auth|
checkins = FbGraph::User.new('me', :access_token => URI.encode(auth.token)).checkins
if checkins != nil
checkins.each do |checkin|
[...]
end
end
end
end
end
(the whole code: https://gist.github.com/966509)
The simple answer: does DelayedJob know about the Authentication and FBGraph::User classes? If not, you'll see exactly the behavior you describe: the items will be silently removed from the queue.
See this entry in the Delayed Job Wiki in the Delayed Job Wiki.
Try adding 'require authentication' and 'require fb_graph' (or whatever) in your facebook_job.rb file.