Rails 设计自定义邮件程序

Yol*_*ake 3 ruby ruby-on-rails actionmailer devise

我想向 Devise 添加新的邮件程序方法,这些方法主要复制内置方法的工作流程,但添加了一些参数和不同的视图。

例如 reset_password_instructions 用于两种情况:

  1. 当现有用户只想重置他的密码时。
  2. 当用户邀请另一个用户时,该用户将使用随机密码保存在数据库中。他收到一封带有 reset_password_token 的电子邮件,应该将他重定向到编辑密码页面,以便他以后可以登录。

相同的功能,但我希望第二封电子邮件具有不同的视图,并且我还需要能够传入发送邀请的人的姓名。

这非常令人困惑,因为设计邮件程序调用了一堆其他方法和助手,所以我不知道要重写哪些方法才能实现这一点。

MZa*_*oza 5

要使用自定义邮件程序,请创建一个扩展类Devise::Mailer,如下所示:

class MyMailer < Devise::Mailer   
  helper :application # gives access to all helpers defined within `application_helper`.
  include Devise::Controllers::UrlHelpers # Optional. eg. `confirmation_url`
  default template_path: 'devise/mailer' # to make sure that your mailer uses the devise views
end
Run Code Online (Sandbox Code Playgroud)

然后,在您的 中config/initializers/devise.rb,设置config.mailer"MyMailer".

您现在可以MyMailer像使用任何其他邮件程序一样使用您的邮件。如果您想覆盖特定邮件以添加额外的标题,您可以通过简单地覆盖该方法并super在自定义方法的末尾调用来触发 Devise 的默认行为。

例如,我们可以为confirmation_instructions电子邮件添加一个新标题,如下所示:

def confirmation_instructions(record, token, opts={})
  headers["Custom-header"] = "Bar"
  super
end
Run Code Online (Sandbox Code Playgroud)

您还可以通过手动设置选项哈希来覆盖任何基本标头(from、reply_to 等):

def confirmation_instructions(record, token, opts={})
  headers["Custom-header"] = "Bar"
  opts[:from] = 'my_custom_from@domain.com'
  opts[:reply_to] = 'my_custom_from@domain.com'
  super
end
Run Code Online (Sandbox Code Playgroud)

为了获得预览(如果User是您的设计模型名称):

# test/mailers/previews/my_mailer_preview.rb
# Preview all emails at http://localhost:3000/rails/mailers/my_mailer

class MyMailerPreview < ActionMailer::Preview

  def confirmation_instructions
    MyMailer.confirmation_instructions(User.first, "faketoken", {})
  end

  def reset_password_instructions
    MyMailer.reset_password_instructions(User.first, "faketoken", {})
  end

  def unlock_instructions
    MyMailer.unlock_instructions(User.first, "faketoken", {})
  end
end
Run Code Online (Sandbox Code Playgroud)

为了控制邮件程序将新电子邮件排队的队列名称,请将以下方法添加到您的类(MyMailer上面的 ):

def deliver_later
   Devise::Mailer.delay(queue: 'my_queue').send(...)
end
Run Code Online (Sandbox Code Playgroud)