Sending custom emails with a token

118 views
Skip to first unread message

Steve Slotnick

unread,
Jun 7, 2013, 10:31:30 PM6/7/13
to plataforma...@googlegroups.com
Hi,  

I've seen several threads asking about welcome emails when a new user is created.  I would like to do something similar, but with a few caveats that I think differ from the previous topics:
1) The welcome email needs to have a password reset link (well technically, set password link).  
2) There are 2 types of users (admins and regular users) and the content of the welcome email must be different for each.  Plus I still need the normal password reset emails.
3) The page that allows the user to set their password should be different from the regular recoverable "reset password" page.

I have looked at the Invitable extension, which seems to satisfy the first and third requirements, but doesn't help with the second.  I was going to create my own mailer and simply insert the password reset token, but the generate_reset_password_token! is protected.  The problem I'm having is that the generation of tokens seems coupled to the sending of the mails, so calling send_reset_password_instructions forces me to use the :reset_password_instructions mailer.  Of course, I could generate my own token or use User.reset_password_token and insert that into the database myself, but then I'm working around the functionality Devise already provides.

Is there already a way to achieve what I'm looking for?  If not, is there a reason this coupling exists between generating the token and sending the mail?  I'm happy to submit a patch making generate_reset_password_token! public.

Thanks,
--Steve

Steve Slotnick

unread,
Jun 11, 2013, 5:51:34 PM6/11/13
to plataforma...@googlegroups.com

Nicholas Rutherford

unread,
May 18, 2015, 11:07:16 AM5/18/15
to plataforma...@googlegroups.com
Hi Steve / others
It looks like you got this working, but there are no docs or wiki page so I'm curious how you did this? 

I want to use set_reset_password_token to set the recovery token as normal, then pass it to my own mailer and send my own email (i.e. not use the send_reset method) but I'm just getting method missing errors when I call or use send on my resource. Maybe something weird going on with rails concerns and method visibility? (I don't use them).

Thanks,
Nick

Steve Slotnick

unread,
May 20, 2015, 2:46:02 PM5/20/15
to plataforma...@googlegroups.com
Hi Nick,

I did get this working, but my approach may not work with the latest version of devise.

I previously submitted a PR that added the method ensure_confirmation_token! to confirmable.rb and recoverable.rb: https://github.com/plataformatec/devise/pull/2464
That allowed me to call ensure_confirmation_token!, construct the confirmation URL (including token) and pass that into my own mailer, just as you describe.

However, it looks like my ensure_confirmation_token! method was removed when changes were made to HMAC the token: https://github.com/plataformatec/devise/commit/143794d701bcd7b8c900c5bb8a216026c3c68afc#diff-fa817bf486c518644016136465d914b2L52

Someone else and I posted a comment on that commit but never received a response. As a result, we've just avoided upgrading. But you may be able to reach out to the powers that be and find out why those methods were removed and what the recommended approach is now. In the worst case it looks like you may be able to copy the HMAC generation code from the new version of send_password_reset_instructions and just create your own token which you save directly into the model: https://github.com/plataformatec/devise/blob/master/lib/devise/models/recoverable.rb#L106

Hope this helps. Let me know if you find a better solution!

Thanks,
--Steve

Nicholas Rutherford

unread,
May 20, 2015, 6:33:10 PM5/20/15
to plataforma...@googlegroups.com
Hi, thanks for replying!
I did this in the end, which might be useful in upgrading.

First off I had to upgrade devise from 3.2.2 to 3.4.1, as some methods in the recoverable module have changed.

In my mailer (rails 4.1):

def added_to_group(group_member)
    @group = group_member.group
    @member = group_member.member
    @token = @member.create_reset_password_token
    mail to: group_member.email,
         subject: 'Somesite group membership notice'
  end

In the mail template (plain text)

<%= edit_member_password_url(reset_password_token: @token) %>

the model method: 

def create_reset_password_token
  send :set_reset_password_token
end

This can probably be refactored (perhaps drop send, since it's a protected method on the same object) but I don't know if rails concerns do something weird there.

It seems like this should be public API. Don't see why we have to send a default email at the same time as set the token, rather than just set a token, or at least be able to specify which email gets sent.
May be a simple PR changing the set_reset_password_token method visibility & adding some tests?

Hope that helps.
Nick

--

---
You received this message because you are subscribed to a topic in the Google Groups "Devise" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/plataformatec-devise/jb4XAnAv2ZE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to plataformatec-de...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages