21

I'm working on a fairly traditional forgot password email - I want to email the user a password change token embedded in a link that they can click on in order to change their password. I'm emailing via the traditional ActionMailer.

If I use a normal link_to tag

<%= link_to "click here", :controller => foo, :action => 'bar', :token => token %>

I get a relative link - rather useless from an email.

If I add in

:only_path => false, then it errors saying I need to set default_url_options[:host]. The ActionController docs imply that you do that by overriding the #default_url_options methods in your controller. Surely there's a configuration option to tell Rails what it's hostname is without adding my own config file, parsing it, etc?

lulalala
  • 17,572
  • 15
  • 110
  • 169
edebill
  • 7,655
  • 5
  • 32
  • 31

7 Answers7

37

default_url_options is available from config.action_mailer and should be set in your environment's configuration file.

For example, in config/environments/production.rb:

config.action_mailer.default_url_options = {
  :host => 'www.yourdomain.com'
}

For local testing, modify config/environments/development.rb:

config.action_mailer.default_url_options = {
  :host => '127.0.0.1',
  :port => 3000
}

Then, assuming you have a named route called forgot_password_login, you can generate the login link URL in your mailer using something like this:

forgot_password_login_url(:token => 'a7s8q15sk2...')
Bryan Ash
  • 4,385
  • 3
  • 41
  • 57
26

You probably want to set :protocol => 'https' as well, btw.

config.action_mailer.default_url_options = { 
    :host => "portal.example.com", 
    :protocol => 'https' 
}
mcr
  • 4,615
  • 2
  • 31
  • 30
  • Thanks for the :protocol => 'https' pointer. using 'portal.example.com' does not seem to work properly, at least with Devise mailers. The resulting urls begin with 'https://example.com/' regardless of the subdomain). – Kevin Aug 22 '12 at 03:03
4

There is another alternative, as described in http://pivotallabs.com/how-i-leaned-to-stop-hating-and-love-action-mailer/

This solution has the advantage that it doesn't require any configuration (so less of a hassle), and works fine as long as you send emails from within controllers.

But if you plan on sending email without going through a controller (e.g. from command line or in response to another email), you need the static configuration.

radex
  • 6,336
  • 4
  • 30
  • 39
Michael Reinsch
  • 579
  • 4
  • 8
  • That's a good tip, though I'm afraid I need the static configuration. For some reason, I keep running into more and more processing that needs to happen outside of a web hit. – edebill Apr 23 '10 at 16:28
  • current link. http://pivotallabs.com/how-i-leaned-to-stop-hating-and-love-action-mailer/ – Sudhir Apr 08 '13 at 07:35
0

Setting default_url_options directly is deprecated in Rails 3.1. Use url_for instead.

Add parameter :protocol to override default value (http), :protocol => 'https://'. This will create url starting with "https://..." instead of default "http://"

Andrei Petrenko
  • 3,922
  • 3
  • 31
  • 53
Sameer
  • 17
  • 2
0

Interestingly, I had the same issue as you did, but in unit tests (while following Michael Hartl's railstutorial). I had this line in my test.rb file, but that didn't help:

config.action_mailer.default_url_options = { host: 'example.com', protocol: 'http' }

I've also added another line like this to test.rb, and surprisingly this solved the issue

default_url_options = { host: 'example.com', protocol: 'http' }
Zhenya
  • 6,020
  • 6
  • 34
  • 42
-1

Setting default_url_options directly is deprecated in Rails 3.1

Use the url_for helper to create it:

<%= link_to "click here", url_for(:controller => foo, :action => 'bar', :token => token, :host => 'www.yourdomain.com') %>
Joe
  • 796
  • 1
  • 7
  • 15
-2

Can you just do

<%="click here", :controller => foo, :action => 'bar', :token => token, :host=>request.host -%>
Rob Di Marco
  • 43,054
  • 9
  • 66
  • 56
  • 5
    request isn't available from within a mailer – John Douthat Apr 28 '09 at 18:00
  • Exactly. I could pass it as one of the parameters to the email generation - but we just decided to move this particular email to being sent from our Application Server instead of the web front-end. I think that means I need to make that custom config file that has the URL of the frontend website in it. – edebill Apr 28 '09 at 18:26
  • doh, missed the mailer part of it – Rob Di Marco Apr 28 '09 at 21:12