Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sidekiq and rails 4 actionmailer never delivers emails

I've setup sidekiq in a rails 4 application for sending emails and processing background jobs. I have also devise which I am using devise_async and a typical contact form emailer. I am using gmail for sending emails.

If I remove sidekiq, it sends the emails normally through gmail (both devise and contact form) but when I am enabling it, it doesn't work (neither devise_async neither contact form). Sidekiq shows that the background jobs starts and finishes successfully (I also see them through the sinatra app that it's been processed) but the email never been delivered.

In development, the console shows that the emails sent (both with devise_async and from contact form, as they are processed with sidekiq successfully).

What I've already have try:

  • I've added the github branch for rails4 of sidekiq (I've also tried the master)
  • I've updated and check redis version to be greater than 2.4 (it's 2.6.14)
  • I am running sidekiq with bundle exec sidekiq

but nothing worked. I am using ruby 2.0.0-p247.

I have also setup image processing with sidekiq in this app and works perfectly both in development and in production.

I am not doing anything fancy but I am adding the code for completion:

My mailer code:

  def send_message
   @message = Message.new(message_params)
   if @message.save
     ContactMailer.delay.contact_form(@message.id)
   end
 end

My mailer:

  def contact_form(message_id)
    message = Message.where(id: message_id).first
    @email = message.email
    @message = message.text
    mail(to: "[email protected]", subject: "Message from contact form")
  end

and my configuration for production (which it works without sidekiq):

  config.action_mailer.delivery_method = :smtp
  ActionMailer::Base.smtp_settings = {
    :address              => "smtp.gmail.com",
    :port                 => 587,
    :domain               => "gmail.com",
    :authentication       => "plain",
    :enable_starttls_auto => true,
    :user_name            => "myusername",
    :password             => "mypassword"
  }
  config.action_mailer.default_url_options = { :host => "mydomain.com" }

And here a typical sidekiq queue:

    /home/john/.rvm/gems/ruby-2.0.0-p247@cluey/bundler/gems/sidekiq-4ed6eba8aff1/lib/sidekiq/rails.rb:14: warning: toplevel constant Queue referenced by Sidekiq::Client::Queue
    2013-07-19T09:47:56Z 20112 TID-1a5mkc INFO: Booting Sidekiq 2.5.2 with Redis at redis://localhost:6379/0
    2013-07-19T09:47:56Z 20112 TID-1a5mkc INFO: Running in ruby 2.0.0p247 (2013-06-27 revision 41674) [i686-linux]
    2013-07-19T09:47:56Z 20112 TID-1a5mkc INFO: See LICENSE and the LGPL-3.0 for licensing details.
    2013-07-19T09:47:56Z 20112 TID-1a5mkc INFO: Starting processing, hit Ctrl-C to stop
    2013-07-19T09:48:11Z 20112 TID-1u2z02 Devise::Async::Backend::Sidekiq JID-4a7e66a14deab112191e4b49 INFO: start
    2013-07-19T09:48:12Z 20112 TID-1u2z02 Devise::Async::Backend::Sidekiq JID-4a7e66a14deab112191e4b49 INFO: done: 1.214 sec
    2013-07-19T09:48:50Z 20112 TID-1u2z02 Devise::Async::Backend::Sidekiq JID-32191822b789f5b6896a5353 INFO: start
2013-07-19T09:48:51Z 20112 TID-1u2z02 Devise::Async::Backend::Sidekiq JID-32191822b789f5b6896a5353 INFO: done: 0.143 sec
2013-07-19T09:49:29Z 20112 TID-1u2z02 Sidekiq::Extensions::DelayedMailer JID-c1911e0c4b72295dc067d57f INFO: start
2013-07-19T09:49:29Z 20112 TID-1u2z02 Sidekiq::Extensions::DelayedMailer JID-c1911e0c4b72295dc067d57f INFO: done: 0.152 sec

I think it has to do with actionmailer and sidekiq but I don't know how to debug, everything seems to work but the emails never delivered.

like image 642
JohnDel Avatar asked Jul 19 '13 10:07

JohnDel


2 Answers

I found it, you have to run sidekiq like this:

RAILS_ENV=production bundle exec sidekiq -D

to run in production. It's the same issue as the assets precompile.

like image 130
JohnDel Avatar answered Sep 28 '22 03:09

JohnDel


My setup is the same as this:

  • Rails 4
  • Ruby 1.9.3
  • actionmailer
  • sidekiq
  • devise_async

My code to run the mailer runs just fine and exits without any errors - but nothing is done and no email is sent. From my mailer:

logger.debug "about to mail"
logger.debug Rails.application.config.action_mailer.sendmail_settings.inspect
mail(to: purchase.email, subject: 'Your key')
logger.debug "mail done!"

That code is called from a sidekiq job. I can see in the rails logs the messages from the debug lines, confirming that this line of code is called. I also see the values of the sendmail_settings, confirming that the settings are the ones from development.rb.

So, just for giggles, I changed the settings to this in development.rb:

config.action_mailer.sendmail_settings = { :location => '/bogus/doesnt/exist' }

Of course after every one of these changes I purge the webroot and completely reload the app, and restart my servers.

Now I see the debug line print out the bogus config value, and still the mail(...) function is executing without any error. This is despite this

config.action_mailer.raise_delivery_errors = true
config.action_mailer.perform_deliveries = true

being set in the config (and being confirmed as being set by debug lines). My mail templates are rendered and the whole thing works, but the sendmail command is never executed, or even tried.

So then I looked at the source code in /var/lib/gems for both Mail and ActionMailer

Action Mailer source

...and I see that the mail(...) function ends with just "m" - so it returns the Mail object. I could not see anywhere in the mail(...) function where the mail is actually sent.

I added debug log lines to the send(...) function in the ActionMailer gem, and I see that in the logs. I added debug to the smtp deliver function in the Mail gem, and its never called.

So I tried calling "deliver" on that returned object thus:

outmail = mail(to: purchase.email, subject: 'Your key')
outmail.deliver

Now, my mail works. I have no idea what is going on here. If this is useful to anyone else I hope it helps. I have wasted a day of dev time on this, so I'm going to just take it as "it works" and check it in.

like image 45
Sez Avatar answered Sep 28 '22 03:09

Sez