Sidekiq和Rails 4的ActionMailer无法发送电子邮件

12

我已经在Rails 4应用程序中设置了Sidekiq,用于发送电子邮件和处理后台作业。我还使用Devise,并使用Devise Async和典型的联系表单电子邮件程序。我正在使用Gmail发送电子邮件。

如果我删除Sidekiq,它会通过Gmail正常发送电子邮件(Devise和联系表单都可以),但是当我启用它时,它无法正常工作(无论是Devise Async还是联系表单)。Sidekiq显示后台作业已经成功启动和完成(我也可以通过Sinatra应用程序看到它们已被处理),但电子邮件从未被传送。

在开发环境中,控制台显示电子邮件已发送(Devise Async和联系表单均已成功处理)。

我已经尝试过的:

  • 我已添加了适用于Rails 4的Sidekiq的GitHub分支(也尝试过主分支)
  • 我已更新并检查Redis版本是否大于2.4(它是2.6.14)
  • 我正在使用bundle exec sidekiq运行Sidekiq

但是什么都没起作用。我正在使用Ruby 2.0.0-p247。

我还在此应用程序中设置了使用Sidekiq的图像处理,无论是在开发还是生产环境中都能够完美运行。

我没有做什么花哨的东西,但我会添加代码以供查看:

我的邮件程序代码:

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

我的邮件客户端:

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

我的生产环境配置(没有使用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" }

这里是一个典型的 Sidekiq 队列:

    /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

我认为这与actionmailer和sidekiq有关,但我不知道如何进行调试,一切似乎都正常,但电子邮件从未被发送。


1
日志文件中包含有用的信息吗? - Jon Cairns
仅出现此警告:me/ujohn/.rvm/gems/ruby-2.0.0-p247@cluey/bundler/gems/sidekiq-4ed6eba8aff1/lib/sidekiq/rails.rb:14: 警告:Sidekiq::Client::Queue引用了顶级常量Queue,但sidekiq的队列似乎运行正常。使用actionmailer处理电子邮件的过程似乎已经损坏。 - JohnDel
这听起来像是一个错误,因为你似乎做了正确的事情。我会在版本库上提出这个问题。 - Jon Cairns
4个回答

18

我找到了,你必须这样运行sidekiq:

RAILS_ENV=production bundle exec sidekiq -D

要在生产环境中运行。这与资产预编译的问题相同。


在运行该命令后,我收到了“无效选项:-D”错误。使用“RAILS_ENV=production bundle exec sidekiq -d”命令可以正常工作。 - webster

2

我的设置与以下内容相同:

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

我的代码可以成功运行邮件程序并且没有任何错误 - 但是没有任何操作和邮件发送。来自我的邮件程序:

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!"

这段代码是从一个Sidekiq工作任务调用的。我可以在Rails日志中看到来自调试行的消息,确认此代码行已调用。我还看到了sendmail_settings的值,确认这些设置是来自development.rb文件的。

所以,只是出于娱乐,我在development.rb中将设置更改为:

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

当然,在进行这些更改后,我会清空Webroot并重新加载应用程序,并重启我的服务器。

现在我看到调试行打印出虚假的配置值,而且mail(...)函数执行时没有任何错误。尽管如此

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

已在配置中设置(并通过调试行确认已设置)。我的邮件模板已呈现,整个过程都可以运行,但 sendmail 命令从未被执行,甚至没有尝试。

然后我查看了 Mail 和 ActionMailer 的 /var/lib/gems 源代码

Action Mailer 源代码

... 我发现 mail(...) 函数以 "m" 结尾,因此它返回 Mail 对象。我无法在 mail(...) 函数中找到实际发送邮件的任何位置。

我在 ActionMailer gem 中的 send(...) 函数中添加了调试日志行,并在日志中看到了它。我在 Mail gem 中的 smtp deliver 函数中添加了调试日志,但从未被调用。

因此,我尝试对返回的对象调用 "deliver":

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

现在,我的邮件已经可以正常工作了。我不知道到底发生了什么。如果对其他人有用的话,我希望这能够帮助到他们。我浪费了一整天的时间来解决这个问题,所以现在我只想把它算作“可以工作”并提交代码。

1
你的电子邮件无法发送,因为它没有发件人地址。https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/extensions/action_mailer.rb#L20 - Mike Perham

1

0

对于任何可能从中受益的人,我是这样运行sidekiq的:

worker: bundle exec sidekiq -q default -q mailers -t 25 -c 3 ...

在使用heroku的Procfile上运行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接