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.37k stars 3.01k forks source link

Override default password reset email #1809

Closed chdsbd closed 10 months 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 6 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 6 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 5 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 2 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 10 months 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 8 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.