Nicholas.V
Nicholas.V

Reputation: 1936

Rails 4 ActionMailer subdomain urls

When a rails 4 application is hosted on a subdomain e.g. sub.domain.com, how can you get urls in Action Mailer templates to link to the subdomain correctly?

config/environments/production.rb:

config.action_mailer.default_url_options = { :host => 'sub.domain.com' }

action mailer template link example:

<%= user_url(@user) %>

In the email, the link shows as www.domain.com/users/1 rather then sub.domain.com/users/1

Upvotes: 4

Views: 4752

Answers (4)

richardun
richardun

Reputation: 713

I doubt this is still an issue for you, but I thought I'd add something helpful I found related to this.

Aside from adding your default_url_options in the various config files (be sure that you add that in all environments you need it), you will want to get the whole url, not just the path.

<%= url_for() %>

You can specify a subdomain or domain as a parameter, as well as several other options (from apidock):

url_for(options = nil) public Generate a url based on the options provided, default_url_options and the routes defined in routes.rb. The following options are supported:

:only_path - If true, the relative url is returned. Defaults to false.

:protocol - The protocol to connect to. Defaults to ‘http’.

:host - Specifies the host the link should be targeted at. If :only_path is false, this option must be provided either explicitly, or via default_url_options.

:subdomain - Specifies the subdomain of the link, using the tld_length to split the subdomain from the host. If false, removes all subdomains from the host part of the link.

:domain - Specifies the domain of the link, using the tld_length to split the domain from the host.

:tld_length - Number of labels the TLD id composed of, only used if :subdomain or :domain are supplied. Defaults to ActionDispatch::Http::URL.tld_length, which in turn defaults to 1.

:port - Optionally specify the port to connect to.

:anchor - An anchor name to be appended to the path.

:trailing_slash - If true, adds a trailing slash, as in “/archive/2009/”

:script_name - Specifies application path relative to domain root. If provided, prepends application path.

Any other key (:controller, :action, etc.) given to url_for is forwarded to the Routes module.

I wound up using link_to with the "_url" end to the route. Like this:

<%= link_to 'Yes', response_approvals_url(t: @secret_token) %>

Upvotes: 4

jimagic
jimagic

Reputation: 4065

For more detailed information click here http://railscasts.com/episodes/221-subdomains-in-rails-3 and here https://github.com/plataformatec/devise/wiki/How-To:-Send-emails-from-subdomains

 module UrlHelper
      def with_subdomain(subdomain)
        subdomain = (subdomain || "")
        subdomain += "." unless subdomain.empty?
        [subdomain, request.domain, request.port_string].join
      end

      def url_for(options = nil)
        if options.kind_of?(Hash) && options.has_key?(:subdomain)
          options[:host] = with_subdomain(options.delete(:subdomain))
        end
        super
      end
    end

    class ApplicationController < ActionController::Base
      include UrlHelper
    end 

Add the following code to the file app/helpers/url_helper.rb

def set_mailer_url_options
    ActionMailer::Base.default_url_options[:host] = with_subdomain(request.subdomain)
end

and modify the file app/controllers/application_controller.rb to add:

before_filter :set_mailer_url_options

Upvotes: 1

Nicholas.V
Nicholas.V

Reputation: 1936

I don't believe it, a caching issue. I use delayed_job https://github.com/collectiveidea/delayed_job to run the mailer. Turns out that when the delayed job script is running it seems to cache the mailer templates.

Solution: RAILS_ENV=production bin/delayed_job restart

That's it! Pays to know what is being cached and where.

Upvotes: 0

jimagic
jimagic

Reputation: 4065

It’s actually easy. The best suggestion I have for solving this problem is that you create a before_filter that sets it on each request in ApplicationController.rb like so:

before_filter :set_mailer_host

  def set_mailer_host
    ActionMailer::Base.default_url_options[:host] = request.host_with_port
  end

Upvotes: 6

Related Questions