From f42408592488e199b3b93272d1a6413eb579a79b Mon Sep 17 00:00:00 2001
From: Valentin Deniaud <vdeniaud@entrouvert.com>
Date: Wed, 16 Oct 2019 11:03:32 +0200
Subject: [PATCH 1/2] utils: handle per ou template in send_templated_mail
 (#35774)

---
 src/authentic2/utils/__init__.py | 23 ++++++++------
 tests/test_utils.py              | 51 +++++++++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 10 deletions(-)

diff --git a/src/authentic2/utils/__init__.py b/src/authentic2/utils/__init__.py
index 5147915c..7e699ab0 100644
--- a/src/authentic2/utils/__init__.py
+++ b/src/authentic2/utils/__init__.py
@@ -613,7 +613,8 @@ def get_fields_and_labels(*args):
 
 def send_templated_mail(user_or_email, template_names, context=None, with_html=True,
                         from_email=None, request=None, legacy_subject_templates=None,
-                        legacy_body_templates=None, legacy_html_body_templates=None, **kwargs):
+                        legacy_body_templates=None, legacy_html_body_templates=None,
+                        per_ou_templates=False, **kwargs):
     '''Send mail to an user by using templates:
        - <template_name>_subject.txt for the subject
        - <template_name>_body.txt for the plain text body
@@ -622,6 +623,12 @@ def send_templated_mail(user_or_email, template_names, context=None, with_html=T
     from .. import middleware
     if isinstance(template_names, six.string_types):
         template_names = [template_names]
+    if per_ou_templates and getattr(user_or_email, 'ou', None):
+        new_template_names = []
+        for template in template_names:
+            new_template_names.append('_'.join((template, user_or_email.ou.slug)))
+            new_template_names.append(template)
+        template_names = new_template_names
     if hasattr(user_or_email, 'email'):
         user_or_email = user_or_email.email
     if not request:
@@ -645,6 +652,7 @@ def send_templated_mail(user_or_email, template_names, context=None, with_html=T
             html_body = render_to_string(html_body_template_names, ctx, request=request)
         except TemplateDoesNotExist:
             html_body = None
+
     send_mail(subject, body, from_email or settings.DEFAULT_FROM_EMAIL, [user_or_email],
               html_message=html_body, **kwargs)
 
@@ -751,9 +759,7 @@ def send_account_deletion_code(request, user):
         'deletion_url': deletion_url}
     template_names = [
         'authentic2/account_deletion_code']
-    if user.ou:
-        template_names.insert(0, 'authentic2/account_deletion_code_%s' % user.ou.slug)
-    send_templated_mail(user.email, template_names, context, request=request)
+    send_templated_mail(user, template_names, context, request=request, per_ou_templates=True)
     logger.info(u'account deletion code sent to %s', user.email)
 
 
@@ -769,9 +775,7 @@ def send_account_deletion_mail(request, user):
         'site': request.get_host()}
     template_names = [
         'authentic2/account_delete_notification']
-    if user.ou:
-        template_names.insert(0, 'authentic2/account_delete_notification_%s' % user.ou.slug)
-    send_templated_mail(user.email, template_names, context, request=request)
+    send_templated_mail(user, template_names, context, request=request, per_ou_templates=True)
     logger.info(u'account deletion mail sent to %s', user.email)
 
 
@@ -826,9 +830,10 @@ def send_password_reset_mail(user, template_names=None, request=None,
                                                        set_random_password=set_random_password,
                                                        sign_next_url=sign_next_url)
 
-    send_templated_mail(user.email, template_names, ctx, request=request,
+    send_templated_mail(user, template_names, ctx, request=request,
                         legacy_subject_templates=legacy_subject_templates,
-                        legacy_body_templates=legacy_body_templates, **kwargs)
+                        legacy_body_templates=legacy_body_templates,
+                        per_ou_templates=True, **kwargs)
     logger.info(u'password reset request for user %s, email sent to %s '
                 'with token %s', user, user.email, token[:9])
 
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 69c2c7b6..c4ca1a6e 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -17,10 +17,12 @@
 
 from django.contrib.auth.middleware import AuthenticationMiddleware
 from django.contrib.sessions.middleware import SessionMiddleware
+from django.core import mail
 
 from authentic2.utils import (good_next_url, same_origin, select_next_url,
                               user_can_change_password, login,
-                              get_authentication_events, authenticate)
+                              get_authentication_events, authenticate,
+                              send_templated_mail)
 
 
 def test_good_next_url(db, rf, settings):
@@ -116,3 +118,50 @@ def test_remember_cookie(rf):
     request.COOKIES['preferrence'] = '1 2 3 4 5'
     prepend_remember_cookie(request, response, 'preferrence', 7)
     assert response.cookies['preferrence'].value == '7 1 2 3 4'
+
+
+def test_send_templated_mail_template_selection(db, tmp_path, settings, simple_user):
+    settings.TEMPLATES[0]['DIRS'].append(str(tmp_path))
+    templates = {}
+    settings.TEMPLATES[0]['APP_DIRS'] = False
+    settings.TEMPLATES[0]['OPTIONS']['loaders'] = [
+            ('django.template.loaders.locmem.Loader', templates)
+    ]
+    default_template = 'default_template'
+    specific_template = 'specific_template'
+    default_template_ou = '_'.join((default_template, simple_user.ou.slug))
+    specific_template_ou = '_'.join((specific_template, simple_user.ou.slug))
+    template_names = [specific_template, default_template]
+
+    def add_template(template):
+        extensions = ['_body.html', '_body.txt', '_subject.txt']
+        for ext in extensions:
+            templates[template + ext] = template
+
+    add_template(default_template)
+    send_templated_mail(simple_user, template_names, per_ou_templates=True)
+    assert len(mail.outbox) == 1
+    sent_mail = mail.outbox.pop()
+    assert sent_mail.subject == default_template
+    assert sent_mail.body == default_template
+
+    add_template(default_template_ou)
+    send_templated_mail(simple_user, template_names, per_ou_templates=True)
+    assert len(mail.outbox) == 1
+    sent_mail = mail.outbox.pop()
+    assert sent_mail.subject == default_template_ou
+    assert sent_mail.body == default_template_ou
+
+    add_template(specific_template)
+    send_templated_mail(simple_user, template_names, per_ou_templates=True)
+    assert len(mail.outbox) == 1
+    sent_mail = mail.outbox.pop()
+    assert sent_mail.subject == specific_template
+    assert sent_mail.body == specific_template
+
+    add_template(specific_template_ou)
+    send_templated_mail(simple_user, template_names, per_ou_templates=True)
+    assert len(mail.outbox) == 1
+    sent_mail = mail.outbox.pop()
+    assert sent_mail.subject == specific_template_ou
+    assert sent_mail.body == specific_template_ou
-- 
2.20.1

