# Override Devise to send mails with async
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
默认的话使用 devise 内部内置的发送邮件的方法,也可以进行覆盖,自定义邮件发送。但是要注意修改devise.rb
文件:
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
sidekiq
在 application.rb 文件中加入如下代码:config.active_job.queue_adapter = :sidekiq
mailers
,因此要在sidekiq.yml
文件中加入此队列。
- [mailers, 3]
development.log 文件:
[ActiveJob] Enqueued ActionMailer::DeliveryJob (Job ID: 6a5e3f3f-bccf-4fc7-89e0-f16f63918aa0) to Sidekiq(mailers) with arguments: "Devise::Mailer", "reset_password_instructions", "deliver_now", #>, "CpfoqSDN3z6zvA9yiUsL", {}
sidekiq.log 文件:
2017-04-09T08:53:57.511Z 24351 TID-y44z8 ActionMailer::DeliveryJob JID-fede8f1837ccca19b5dbf262 INFO: start
2017-04-09T08:53:58.493Z 24351 TID-y44z8 ActionMailer::DeliveryJob JID-fede8f1837ccca19b5dbf262 INFO: done: 0.983 sec
send_devise_notification(notification, *args)
参数信息:I, [2017-04-09T17:00:56.308408 #21573] INFO -- : notification: reset_password_instructions
I, [2017-04-09T17:00:56.308512 #21573] INFO -- : args: ["hmNJj3Gszwvswd2VjxQL", {}]
I, [2017-04-09T17:00:56.498526 #21573] INFO -- : devise_mailer: Devise::Mailer Class
因此可知
类: Devise::Mailer
方法:reset_password_instructions
devise/app/mailers/devise/mailer.rb
if defined?(ActionMailer)
class Devise::Mailer < Devise.parent_mailer.constantize
include Devise::Mailers::Helpers
def confirmation_instructions(record, token, opts={})
@token = token
devise_mail(record, :confirmation_instructions, opts)
end
def reset_password_instructions(record, token, opts={})
@token = token
devise_mail(record, :reset_password_instructions, opts)
end
def unlock_instructions(record, token, opts={})
@token = token
devise_mail(record, :unlock_instructions, opts)
end
def email_changed(record, opts={})
devise_mail(record, :email_changed, opts)
end
def password_change(record, opts={})
devise_mail(record, :password_change, opts)
end
end
end
因此:devise_mailer
会根据不同的参数调用不同的方法。
Devise.parent_mailer.constantize
解析:# devise/lib/devise.rb
module Devise
# The parent mailer all Devise mailers inherit from.
# Defaults to ActionMailer::Base. This should be set early
# in the initialization process and should be set to a string.
mattr_accessor :parent_mailer
@@parent_mailer = "ActionMailer::Base"
end
发送邮件的方法 devise_mail
定义在 module Devise::Mailers::Helpers
中,这是发送邮件的具体实现。
# 发送邮件 record 就是User记录, action 是 :reset_password_instructions
def devise_mail(record, action, opts = {}, &block)
initialize_from_record(record)
mail headers_for(action, opts), &block
end
# 一些初始化的工作
def initialize_from_record(record)
@scope_name = Devise::Mapping.find_scope!(record)
@resource = instance_variable_set("@#{devise_mapping.name}", record)
end
# 设置一些头信息
def headers_for(action, opts)
headers = {
subject: subject_for(action),
to: resource.email,
from: mailer_sender(devise_mapping),
reply_to: mailer_reply_to(devise_mapping),
template_path: template_paths,
template_name: action
}.merge(opts)
@email = headers[:to]
headers
end
headers 的结果类似:
headers: {:subject=>"重置密码信息", :to=>"[email protected]", :from=>"[email protected]", :reply_to=>"[email protected]", :template_path=>["devise/mailer"], :template_name=>:reset_password_instructions}