pennersr / django-allauth

Integrated set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication.
https://allauth.org
MIT License
9.55k stars 3.04k forks source link

Override default password reset email #1809

Closed chdsbd closed 1 year ago

chdsbd commented 7 years ago

I'm attempting to override the default password reset email to send an HTML email, but I cannot find documentation on this.

I added my template to templates/account/email/password_reset_key_message.html, but that didn't override the default.

What is the proper and concise way to do this?

Related https://github.com/pennersr/django-allauth/issues/682

thongly commented 7 years ago

@pennersr - I just hit this too and was thinking of putting in a pull request for a possible override in settings. That way, there's no need to subclass the default adapter just for the sake of a single email template swap.

Let me know if that'd be acceptable as a PR.

@chdsbd - Looks like you'll have to override the default adapter's send_confirmation_email method, which in turn feeds the prefix into the render_email method

CC: @StevenFerreira

thongly commented 7 years ago

Alternatively, you could do a template override in your local django project template directory, and use the exact same naming convention.

https://docs.djangoproject.com/en/1.11/howto/overriding-templates/#overriding-from-the-project-s-templates-directory

Moulde commented 6 years ago

I am trying to do this, and it works for the verify confirmation email, but it seems that the reset password email is still using the default templates/registration/password_reset_email.html, and it doesn't hit the render_email function, or any of the email functions in the AccountAdaptor.

I am a bit at a loss. Here is the way I previously changed the default AccountAdapter to send a custom url https://github.com/Tivix/django-rest-auth/issues/389#issuecomment-350487890

briandkim93 commented 6 years ago

You need to create your own PasswordResetSerializer with a custom save method and override the default in the settings.

Check out this solution here: https://stackoverflow.com/a/52111127/7234587

To make an HTML email simply replace 'email_template_name' with 'html_email_template_name' in the save options. Then use an HTML file instead of a text file.

volkandkaya commented 6 years ago

If you dont need to use HTML just create a file called password_reset_key_message.txt in templates/account/email and it will work.

https://github.com/pennersr/django-allauth/blob/master/allauth/templates/account/email/password_reset_key_message.txt

Brunux commented 5 years ago

Two more cents here watch out for the actual reset password URL syntax https://github.com/django/django/blob/master/django/contrib/admin/templates/registration/password_reset_email.html#L6 It may change in the future.

alexjpm commented 4 years ago

In case anyone is looking at this, works for me just by changing password_reset_key_message.txt and password_reset_key_subject.txt to have ".html" extensions.

johnvonneumann7 commented 3 years ago

In case anyone is looking at this, works for me just by changing password_reset_key_message.txt and password_reset_key_subject.txt to have ".html" extensions.

I was able to overwrite it by putting password_reset_key_message.html in templates/allauth/account/email/, but However, the protocol and domain uid token data are empty. Is there anything else I should do?

{{ password_reset_url }} will respond, but since we have a separate backend and frontend, we need to override the URL as well.

aabanaag commented 3 years ago

In case anyone is looking at this, works for me just by changing password_reset_key_message.txt and password_reset_key_subject.txt to have ".html" extensions.

I was able to overwrite it by putting password_reset_key_message.html in templates/allauth/account/email/, but However, the protocol and domain uid token data are empty. Is there anything else I should do?

{{ password_reset_url }} will respond, but since we have a separate backend and frontend, we need to override the URL as well.

I have this problem also, I was able to change the template of the password_reset_key_message.html but since I have a separate frontend the generated url is incorrect.

jeffrafter commented 2 years ago

@aabanaag I think you would need to override this to include those fields: https://github.com/pennersr/django-allauth/blob/353386216b79f16709e97bb487c0bbbba2bc0c71/allauth/account/forms.py#L552-L557

Because I didn't want to do that I just made formatted my generated URL specifically:

path('api/password/confirm/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),

Then made two new filters:

@register.filter(name="uid_param")
 def uid_param(url):
     return re.match(r"^(.*)/(.*)/(.*)/$", url).group(2)

 @register.filter(name="token_param")
 def token_param(url):
     return re.match(r"^(.*)/(.*)/(.*)/$", url).group(3)

Then used it:

https://example.com/account/forgot-password/?uid={{ password_reset_url | uid_param }}&token={{ password_reset_url | token_param }}

This is a pretty terrible idea, but kept things small.

joshuakoh1 commented 2 years ago

@jeffrafter Where do you place the register.filter code?

dmwyatt commented 2 years ago

@joshuakoh1 https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/#code-layout

simox11 commented 1 year ago

users.serializers.CustomPasswordResetSerializer

class CustomAllAuthPasswordResetForm(AllAuthPasswordResetForm):
    def save(self, request, **kwargs):
        current_site = config('FRONTEND_DOMAIN')
        email = self.cleaned_data['email']
        token_generator = kwargs.get('token_generator', default_token_generator)
        for user in self.users:
            temp_key = token_generator.make_token(user)
            # send the password reset email
            path = reverse('password_reset_confirm', args=[user_pk_to_url_str(user), temp_key], )
            # custom url frontend
            url = config('FRONTEND_DOMAIN') + '/auth' + path
            context = {
                'current_site': current_site,
                'user': user,
                'password_reset_url': url,
                'request': request,
            }
            get_adapter(request).send_mail('account/email/password_reset_key', email, context)
        return self.cleaned_data['email']
class CustomPasswordResetSerializer(PasswordResetSerializer):
    @property
    def password_reset_form_class(self):
        return CustomAllAuthPasswordResetForm

settings.py

REST_AUTH = {
    'USE_JWT': True,
    'PASSWORD_RESET_SERIALIZER': 'users.serializers.CustomPasswordResetSerializer',
    'PASSWORD_RESET_USE_SITES_DOMAIN': False,
}
pennersr commented 1 year ago

It is not very clear what this ticket is about, one the one hand it is about overriding templates, on the other hand I see people using custom serializers suggesting another package is involved. Closing as it does not clearly pinpoint an issue in allauth.

jarcoal commented 11 months ago

It would be pretty handy if the adapter exposed a method like send_password_reset_email (similar to these) that could allow the customization of that email, beyond simply the template.

I realize it's possible to subclass the send_email method and handle it from there, but a specific method would make it easier.

If there's interest I could take a shot at a PR.