Search code examples
pythondjangoemailemail-verification

is there a custom Django email confirmation link module?


I am building a site where people sign up for dog training classes. The client wants to automatically register the people in a current class for upcoming classes via an email confirmation link.

I would like them to be able to do this without having to log in to the site. So all of the relevant information would need to be contained in the generated link itself. The link would ideally be scrambled in some way, so that random requests from bots would not foul things up.

Is there an existing app/convention that people use to do this with?


Solution

  • You can generate a timestamped token (basically, a hash of the user state) for the user when you create and send the email in the backend. Encode that token and the UID for the user in the URL, then check its validity in your registration view when the link is visited. Hashing user state guarantees (for all practical purposes) that you're not going to run into any issues with bots randomly generating any correct URL's.

    The built-in password reset view in contrib.auth does basically this exact thing. The URL in the reset email sent to the user has two parameters at the end - the base-64 encoded UID and a generated token. The source for the token generation is here: https://github.com/django/django/blob/master/django/contrib/auth/tokens.py, and the related view is password_reset_confirm at https://github.com/django/django/blob/master/django/contrib/auth/views.py

    You could probably implement something very similar for your application, but you'll have to be careful about how you generate the tokens. In the contrib.auth token generator, they hash the entire internal state of the user, including the password hash, which guarantees that the link will only be valid once since the password hash will be changed after the user resets the password. If you want to make sure that a link is only valid once, you'll have to include some other state that is guaranteed to change in the hash.