When you generate a URL in a mailer view, ActionMailer
will raise an error unless you previously
configured it which hostname to use
Show archive.org snapshot
.
There are two options to set the default_url_options
of ActionMailer:
When you are sending mails from outside the request cycle, e.g. ActiveJob/Sidekiq or Cronjobs, you need to configure the default_url_options
in your Rails configuration.
# config/application.rb as fallback/default
Rails.application.default_url_options = { host: 'localhost', port: 3000, protocol: 'http://' }
Rails.application.configure do
# ...
end
# config/environments/staging.rb
Rails.application.default_url_options = { host: 'staging.example.com', protocol: 'https://' }
Rails.application.configure do
# ...
end
# config/environments/production.rb
Rails.application.default_url_options = { host: 'www.example.com', protocol: 'https://' }
Rails.application.configure do
# ...
end
Configuring the correct hostname is quite annoying when you have multiple deployment targets with different hostnames, e.g. a staging server and a production server. Using the hack below you don't need to configure default url options for your mailers, as these are now derived from the request:
class ApplicationController < ActionController::Base
before_action :make_action_mailer_use_request_host_and_protocol
private
def make_action_mailer_use_request_host_and_protocol
ActionMailer::Base.default_url_options[:protocol] = request.protocol
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end
end
If your application server talks only HTTP and relies on the web server for SSL, and if the web server is setting a special HTTPS forwarding header, Rails recognizes that a request originally was on HTTPS and will return the correct protocol.
Caveats:
HOST
header to an application server, that serves requests under a different host e.g. your application server example.com
should not serve requests with the HOST
header hacker.xyz
ActionMailer::Base.default_url_options
after e.g. request specs.