Sidekiq + Devise Mailer with Multiple Subdomains

I have a problem with changing ActionMailer :: Base.default_url_options = {: host => host} at runtime in one of my projects.

Setup: I have several subdomains that use the same Rails application in the backend. I want to send my Devise messages to the Sidekiq queue to users. Developer emails (confirmation, reset -password) contain links, and these links need the correct subdomain.

My environment

rails (4.2.0) sidekiq (3.3.1) devise (3.4.1) devise-async (0.9.0) 

I have before_action in my application_controller

 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 

Now, if I want to reset my password, I always get the default url parameters that I specified in the environment file. If I remove default_url_options from my environments, I get a default Devise error in my sidekiq logs.

 ActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true 

The host is always correctly installed in the controller. I have already debugged this. It seems that the host is not passed sidekiq .. any idea how I can fix this?

I canโ€™t save the subdomain somewhere, because the user can start emails from different subdomains and are not always the same. I need a way to tell Devise which host should be used to send a specific email. Can I redefine the Devise mailer and transfer the host or something like that?

The following solution is impossible in my case: Dynamic domain name in Rails mailer when using sidekiq

Btw: a full workflow is running using devise, devise-async and sidekiq (in development, production, and release). Only the link host is incorrect โ†’ and this is my big problem :-) ..

+5
source share
2 answers

I ended up in the following solution. This solution contains a case where you have several clients, and these clients may have their own email settings and their own domains / subdomains for URLs in emails.

I used my own mailer class and connected to the clientโ€™s custom email settings:

configurations / 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 

Application / senders / 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 

Change the urls in the email view templates:

application / views / Testament / mailer / confirmation_instructions.html.erb

Just change the link to the new url options.

application / views / invent / 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 %> 

That was my decision. If you have any questions, just let me know.

EDIT: Remember to specify the default url parameters in your environment. For example, in your development.rb file - config / environment / development.rb:

 config.action_mailer.default_url_options = { host: "your-host.dev", port: 3000 } 
+1
source

You can rewrite your default url parameters like this in your ApplicationController:

http://edgeguides.rubyonrails.org/action_controller_overview.html#default-url-options

 class ApplicationController < ActionController::Base def default_url_options {:host => host} end end 

OR you can try this answer: fooobar.com/questions/109713 / ...

0
source

Source: https://habr.com/ru/post/1213284/


All Articles