Sidekiq + 设计具有多个子域的邮件程序
Sidekiq + Devise Mailer with multiple Subdomains
我在运行时在我的一个项目中更改 ActionMailer::Base.default_url_options = {:host => host} 时遇到问题。
设置:
我有多个子域在后端使用相同的 Rails-Application。我想通过 Sidekiq 队列将我的 Devise 邮件发送给用户。 Devise 邮件(确认、重置密码)包含链接,这些链接需要特定的子域才能正确。
我的环境
rails (4.2.0)
sidekiq (3.3.1)
devise (3.4.1)
devise-async (0.9.0)
我的 application_controller
中有一个 before_action
class ApplicationController < ActionController::Base
before_action :set_action_mailer_default_url_options
private
def set_action_mailer_default_url_options
host = "my-logic-to-get-the-correct-host"
ActionMailer::Base.default_url_options = {:host => host}
end
end
现在,如果我想重设密码,我总是会得到默认的 url 选项,我已经在环境文件中指定了这些选项。如果我从我的环境中删除 default_url_options,我会在我的 sidekiq 日志中收到默认的 Devise 错误。
ActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
控制器中的主机始终设置正确。我已经调试过了。似乎主机没有传递给 sidekiq..知道我该如何解决这个问题吗?
我无法将子域保存在某处,因为用户可以触发来自不同子域的电子邮件,但并不总是相同的。我需要一种方法来告诉 Devise 应该使用哪个主机来发送特定的电子邮件。我可以覆盖 Devise 邮件程序并传递主机或类似的东西吗?
以下解决方案在我的情况下是不可能的:
Dynamic domain name in Rails action mailer while using sidekiq
顺便说一句:具有设计、设计异步和 sidekiq 本身的完整工作流程(在开发、暂存和生产中)。只有链接的主机不正确 -> 这是我的大问题:-)..
您可以在 ApplicationController 中像这样覆盖默认的 url 选项:
http://edgeguides.rubyonrails.org/action_controller_overview.html#default-url-options
class ApplicationController < ActionController::Base
def default_url_options
{:host => host}
end
end
或者您可以试试这个答案:
我最终采用了以下解决方案。此解决方案包含您有多个客户的情况,这些客户可以拥有自己的电子邮件设置和邮件中 url 的域/子域。
我使用了自己的邮件程序 class 并连接了客户可能的自定义电子邮件设置:
config/initializers/devise.rb:
config.mailer = "DeviseMailer"
config/secrets.yml:
development:
mailer_settings:
customers:
customer_1_identifier_name:
send:
address: "smtp.gmail.com"
port: 587
domain: "example"
user_name: "test@example.com"
email: "noreply@example.com"
password: "secret"
authentication: "plain" # or "login"
ssl: false # or true
tls: false # or true
enable_starttls_auto: true # or false
app/mailers/devise_mailer.rb:
class DeviseMailer < Devise::Mailer
layout 'mailer'
after_action :set_email_settings_and_sender, only: [:reset_password_instructions, :confirmation_instructions]
def reset_password_instructions(record, token, opts={})
@account = record.current_account if record.class == User # set the account of current_user - current_account is an own helper method
super
end
def confirmation_instructions(record, token, opts={})
@account = record.current_account if record.class == User && record.unconfirmed_email.present?
super
end
private
# re-set the email settings for the given user and his account:
def set_email_settings_and_sender
if @account.present? && @account.custom_email_settings?
mail.reply_to = nil
settings = Rails.application.secrets.mailer_settings["customers"][@account.identifier_name]["send"].symbolize_keys
mail.delivery_method.settings.merge!(settings)
mail.from = "#{@account.display_name} <#{settings[:email]}>"
end
end
end
更改电子邮件视图模板中的 urls:
app/views/devise/mailer/confirmation_instructions.html.erb
使用新的 url 选项简单地更改 link..
app/views/devise/reset_password_instructions.html.erb
<% if @account.present? && @account.domain.present? %>
<% link = "#{@account.host_for_links}/auth/password/edit?reset_password_token=#{@token}" %>
<a href="<%= link %>"><%= link %></a>
<% else %>
<a href="<%= edit_password_url(@resource, reset_password_token: @token) %>"><%= edit_password_url(@resource, reset_password_token: @token) %></a>
<% end %>
这是我的解决方案。如果您有任何问题,请告诉我。
编辑:
不要忘记在您的环境中设置默认 url 选项。例如在你的 development.rb - config/environments/development.rb:
config.action_mailer.default_url_options = { host: "your-host.dev", port: 3000 }
我在运行时在我的一个项目中更改 ActionMailer::Base.default_url_options = {:host => host} 时遇到问题。
设置: 我有多个子域在后端使用相同的 Rails-Application。我想通过 Sidekiq 队列将我的 Devise 邮件发送给用户。 Devise 邮件(确认、重置密码)包含链接,这些链接需要特定的子域才能正确。
我的环境
rails (4.2.0)
sidekiq (3.3.1)
devise (3.4.1)
devise-async (0.9.0)
我的 application_controller
中有一个 before_actionclass ApplicationController < ActionController::Base
before_action :set_action_mailer_default_url_options
private
def set_action_mailer_default_url_options
host = "my-logic-to-get-the-correct-host"
ActionMailer::Base.default_url_options = {:host => host}
end
end
现在,如果我想重设密码,我总是会得到默认的 url 选项,我已经在环境文件中指定了这些选项。如果我从我的环境中删除 default_url_options,我会在我的 sidekiq 日志中收到默认的 Devise 错误。
ActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
控制器中的主机始终设置正确。我已经调试过了。似乎主机没有传递给 sidekiq..知道我该如何解决这个问题吗?
我无法将子域保存在某处,因为用户可以触发来自不同子域的电子邮件,但并不总是相同的。我需要一种方法来告诉 Devise 应该使用哪个主机来发送特定的电子邮件。我可以覆盖 Devise 邮件程序并传递主机或类似的东西吗?
以下解决方案在我的情况下是不可能的: Dynamic domain name in Rails action mailer while using sidekiq
顺便说一句:具有设计、设计异步和 sidekiq 本身的完整工作流程(在开发、暂存和生产中)。只有链接的主机不正确 -> 这是我的大问题:-)..
您可以在 ApplicationController 中像这样覆盖默认的 url 选项:
http://edgeguides.rubyonrails.org/action_controller_overview.html#default-url-options
class ApplicationController < ActionController::Base
def default_url_options
{:host => host}
end
end
或者您可以试试这个答案:
我最终采用了以下解决方案。此解决方案包含您有多个客户的情况,这些客户可以拥有自己的电子邮件设置和邮件中 url 的域/子域。
我使用了自己的邮件程序 class 并连接了客户可能的自定义电子邮件设置:
config/initializers/devise.rb:
config.mailer = "DeviseMailer"
config/secrets.yml:
development:
mailer_settings:
customers:
customer_1_identifier_name:
send:
address: "smtp.gmail.com"
port: 587
domain: "example"
user_name: "test@example.com"
email: "noreply@example.com"
password: "secret"
authentication: "plain" # or "login"
ssl: false # or true
tls: false # or true
enable_starttls_auto: true # or false
app/mailers/devise_mailer.rb:
class DeviseMailer < Devise::Mailer
layout 'mailer'
after_action :set_email_settings_and_sender, only: [:reset_password_instructions, :confirmation_instructions]
def reset_password_instructions(record, token, opts={})
@account = record.current_account if record.class == User # set the account of current_user - current_account is an own helper method
super
end
def confirmation_instructions(record, token, opts={})
@account = record.current_account if record.class == User && record.unconfirmed_email.present?
super
end
private
# re-set the email settings for the given user and his account:
def set_email_settings_and_sender
if @account.present? && @account.custom_email_settings?
mail.reply_to = nil
settings = Rails.application.secrets.mailer_settings["customers"][@account.identifier_name]["send"].symbolize_keys
mail.delivery_method.settings.merge!(settings)
mail.from = "#{@account.display_name} <#{settings[:email]}>"
end
end
end
更改电子邮件视图模板中的 urls:
app/views/devise/mailer/confirmation_instructions.html.erb
使用新的 url 选项简单地更改 link..
app/views/devise/reset_password_instructions.html.erb
<% if @account.present? && @account.domain.present? %>
<% link = "#{@account.host_for_links}/auth/password/edit?reset_password_token=#{@token}" %>
<a href="<%= link %>"><%= link %></a>
<% else %>
<a href="<%= edit_password_url(@resource, reset_password_token: @token) %>"><%= edit_password_url(@resource, reset_password_token: @token) %></a>
<% end %>
这是我的解决方案。如果您有任何问题,请告诉我。
编辑: 不要忘记在您的环境中设置默认 url 选项。例如在你的 development.rb - config/environments/development.rb:
config.action_mailer.default_url_options = { host: "your-host.dev", port: 3000 }