Search code examples
djangodjoser

Djoser change email language


Is there a way to change the email that is sent in djoser based on the language of the user instance? I have found this question How do I explicitly specify language of email I want to send?, but it does not seem to be an option in the last version of djoser, since there are no longer views for each action (activation, reset password etc.) or I have not figured out how it works. Also, I have tried inhereting the UserViewSet class and apply the translation, but I do not know if this is the way to do it and how to specify all the urls of djoser.

class UserViewSet(djoser_view.UserViewSet):
    def perform_create(self, serializer):
        user = serializer.save()
        signals.user_registered.send(
            sender=self.__class__, user=user, request=self.request
        )

        context = {"user": user}
        to = [get_user_email(user)]
        language = user.language or 'en-us'
        with translation.override(language):
            if settings.SEND_ACTIVATION_EMAIL:
                settings.EMAIL.activation(self.request, context).send(to)
            elif settings.SEND_CONFIRMATION_EMAIL:
                settings.EMAIL.confirmation(self.request, context).send(to)

    def perform_update(self, serializer):
        super().perform_update(serializer)
        user = serializer.instance
        language = user.language or 'en-us'
        with translation.override(language):
            if settings.SEND_ACTIVATION_EMAIL:
                context = {"user": user}
                to = [get_user_email(user)]
                settings.EMAIL.activation(self.request, context).send(to)


    @action(["post"], detail=False)
    def activation(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.user
        user.is_active = True
        user.save()

        signals.user_activated.send(
            sender=self.__class__, user=user, request=self.request
        )

        language = user.language or 'en-us'
        with translation.override(language):
            if settings.SEND_CONFIRMATION_EMAIL:
                context = {"user": user}
                to = [get_user_email(user)]
                settings.EMAIL.confirmation(self.request, context).send(to)

        return Response(status=status.HTTP_204_NO_CONTENT)

Does anyone have any suggestions or has done this?


Solution

  • Sure you can!

    You correctly identified the action where mail is send.

        @action(["post"], detail=False)
        def activation(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            user = serializer.user
            user.is_active = True
            user.save()
    
            signals.user_activated.send(
                sender=self.__class__, user=user, request=self.request
            )
    
            if settings.SEND_CONFIRMATION_EMAIL:
                context = {"user": user}
                to = [get_user_email(user)]
                settings.EMAIL.confirmation(self.request, context).send(to)
    

    So after subclassing UserViewSet you can provide a template name in activation action.

            if settings.SEND_CONFIRMATION_EMAIL:
                context = {"user": user}
                to = [get_user_email(user)]
                kwargs = {"request": self.request, "context": context}
                if user.country == "Country1":
                    kwargs["template_name"] = "email/country1/activation.html"
                settings.EMAIL.confirmation(**kwargs)).send(to)
    

    Djoser is using templated-mail to create mail content.

    But, as you can see, user entity is passed in the context. So I'd rather advise to tweak your settings a bit and do it in the class that's responsible for generating this email.

    in your app/email.py

    class CountryActivationMail(ActivationEmail):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            if self.context.user.country == "Country1":
                self.template_name = "email/country1/activation.html"
    

    and set CountryActivationMail in djoser settings as explained in the docs.