codeforlife-portal 6.43.0__py2.py3-none-any.whl → 6.43.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codeforlife-portal might be problematic. Click here for more details.

@@ -29,30 +29,6 @@ def kickedEmail(request, schoolName):
29
29
  }
30
30
 
31
31
 
32
- def adminGivenEmail(request, schoolName):
33
-
34
- url = request.build_absolute_uri(reverse("dashboard"))
35
-
36
- return {
37
- "subject": f"You have been made a school or club administrator",
38
- "message": (
39
- f"Administrator control of the school or club '{schoolName}' has been "
40
- f"given to you. Go to {url} to start managing your school or club."
41
- ),
42
- }
43
-
44
-
45
- def adminRevokedEmail(request, schoolName):
46
- return {
47
- "subject": f"You are no longer a school or club administrator",
48
- "message": (
49
- f"Your administrator control of the school or club '{schoolName}' has been "
50
- f"revoked. If you think this is an error, please contact one of the other "
51
- f"administrators in your school or club."
52
- ),
53
- }
54
-
55
-
56
32
  def studentJoinRequestSentEmail(request, schoolName, accessCode):
57
33
  return {
58
34
  "subject": f"School or club join request sent",
@@ -6,14 +6,11 @@ from uuid import uuid4
6
6
 
7
7
  import jwt
8
8
  from common import app_settings
9
- from common.app_settings import domain
10
- from common.mail import campaign_ids, send_dotdigital_email
9
+ from common.mail import campaign_ids, django_send_email, send_dotdigital_email
11
10
  from common.models import Student, Teacher
12
11
  from django.conf import settings
13
12
  from django.contrib.auth.models import User
14
- from django.core.mail import EmailMultiAlternatives
15
13
  from django.http import HttpResponse
16
- from django.template import loader
17
14
  from django.urls import reverse
18
15
  from django.utils import timezone
19
16
  from requests import delete, get, post, put
@@ -31,41 +28,6 @@ class DotmailerUserType(Enum):
31
28
  NO_ACCOUNT = auto()
32
29
 
33
30
 
34
- def send_email(
35
- sender,
36
- recipients,
37
- subject,
38
- text_content,
39
- title,
40
- replace_url=None,
41
- plaintext_template="email.txt",
42
- html_template="email.html",
43
- ):
44
- # add in template for templates to message
45
-
46
- # setup templates
47
- plaintext = loader.get_template(plaintext_template)
48
- html = loader.get_template(html_template)
49
- plaintext_email_context = {"content": text_content}
50
- html_email_context = {"content": text_content, "title": title, "url_prefix": domain()}
51
-
52
- # render templates
53
- plaintext_body = plaintext.render(plaintext_email_context)
54
- original_html_body = html.render(html_email_context)
55
- html_body = original_html_body
56
-
57
- if replace_url:
58
- verify_url = replace_url["verify_url"]
59
- verify_replace_url = re.sub(f"(.*/verify_email/)(.*)", f"\\1", verify_url)
60
- html_body = re.sub(f"({verify_url})(.*){verify_url}", f"\\1\\2{verify_replace_url}", original_html_body)
61
-
62
- # make message using templates
63
- message = EmailMultiAlternatives(subject, plaintext_body, sender, recipients)
64
- message.attach_alternative(html_body, "text/html")
65
-
66
- message.send()
67
-
68
-
69
31
  def generate_token(user, new_email="", preverified=False):
70
32
  if preverified:
71
33
  user.userprofile.is_verified = preverified
@@ -91,6 +53,19 @@ def _newsletter_ticked(data):
91
53
  return "newsletter_ticked" in data and data["newsletter_ticked"]
92
54
 
93
55
 
56
+ def send_email(
57
+ sender,
58
+ recipients,
59
+ subject,
60
+ text_content,
61
+ title,
62
+ replace_url=None,
63
+ plaintext_template="email.txt",
64
+ html_template="email.html",
65
+ ):
66
+ django_send_email(sender, recipients, subject, text_content, title, replace_url, plaintext_template, html_template)
67
+
68
+
94
69
  def send_verification_email(request, user, data, new_email=None, age=None):
95
70
  """
96
71
  Sends emails relating to email address verification.
cfl_common/common/mail.py CHANGED
@@ -3,8 +3,13 @@ from dataclasses import dataclass
3
3
 
4
4
  import requests
5
5
  from common import app_settings
6
+ from common.app_settings import MODULE_NAME, domain
7
+ from django.core.mail import EmailMultiAlternatives
8
+ from django.template import loader
6
9
 
7
10
  campaign_ids = {
11
+ "admin_given": 1569057,
12
+ "admin_revoked": 1569071,
8
13
  "email_change_notification": 1551600,
9
14
  "email_change_verification": 1551594,
10
15
  "reset_password": 1557153,
@@ -34,6 +39,41 @@ class EmailAttachment:
34
39
  content: str
35
40
 
36
41
 
42
+ def django_send_email(
43
+ sender,
44
+ recipients,
45
+ subject,
46
+ text_content,
47
+ title,
48
+ replace_url=None,
49
+ plaintext_template="email.txt",
50
+ html_template="email.html",
51
+ ):
52
+ # add in template for templates to message
53
+
54
+ # setup templates
55
+ plaintext = loader.get_template(plaintext_template)
56
+ html = loader.get_template(html_template)
57
+ plaintext_email_context = {"content": text_content}
58
+ html_email_context = {"content": text_content, "title": title, "url_prefix": domain()}
59
+
60
+ # render templates
61
+ plaintext_body = plaintext.render(plaintext_email_context)
62
+ original_html_body = html.render(html_email_context)
63
+ html_body = original_html_body
64
+
65
+ if replace_url:
66
+ verify_url = replace_url["verify_url"]
67
+ verify_replace_url = re.sub(f"(.*/verify_email/)(.*)", f"\\1", verify_url)
68
+ html_body = re.sub(f"({verify_url})(.*){verify_url}", f"\\1\\2{verify_replace_url}", original_html_body)
69
+
70
+ # make message using templates
71
+ message = EmailMultiAlternatives(subject, plaintext_body, sender, recipients)
72
+ message.attach_alternative(html_body, "text/html")
73
+
74
+ message.send()
75
+
76
+
37
77
  # pylint: disable-next=too-many-arguments
38
78
  def send_dotdigital_email(
39
79
  campaign_id: int,
@@ -71,47 +111,51 @@ def send_dotdigital_email(
71
111
  """
72
112
  # pylint: enable=line-too-long
73
113
 
74
- if auth is None:
75
- auth = app_settings.DOTDIGITAL_AUTH
76
-
77
- body = {
78
- "campaignId": campaign_id,
79
- "toAddresses": to_addresses,
80
- }
81
- if cc_addresses is not None:
82
- body["ccAddresses"] = cc_addresses
83
- if bcc_addresses is not None:
84
- body["bccAddresses"] = bcc_addresses
85
- if from_address is not None:
86
- body["fromAddress"] = from_address
87
- if personalization_values is not None:
88
- body["personalizationValues"] = [
89
- {
90
- "name": key,
91
- "value": value,
92
- }
93
- for key, value in personalization_values.items()
94
- ]
95
- if metadata is not None:
96
- body["metadata"] = metadata
97
- if attachments is not None:
98
- body["attachments"] = [
99
- {
100
- "fileName": attachment.file_name,
101
- "mimeType": attachment.mime_type,
102
- "content": attachment.content,
103
- }
104
- for attachment in attachments
105
- ]
106
-
107
- response = requests.post(
108
- url=f"https://{region}-api.dotdigital.com/v2/email/triggered-campaign",
109
- json=body,
110
- headers={
111
- "accept": "text/plain",
112
- "authorization": auth,
113
- },
114
- timeout=timeout,
115
- )
116
-
117
- assert response.ok, "Failed to send email." f" Reason: {response.reason}." f" Text: {response.text}."
114
+ # Dotdigital emails don't work locally, so if testing emails locally use Django to send a dummy email instead
115
+ if MODULE_NAME == "local":
116
+ django_send_email(from_address, to_addresses, "dummy_subject", "dummy_text_content", "dummy_title")
117
+ else:
118
+ if auth is None:
119
+ auth = app_settings.DOTDIGITAL_AUTH
120
+
121
+ body = {
122
+ "campaignId": campaign_id,
123
+ "toAddresses": to_addresses,
124
+ }
125
+ if cc_addresses is not None:
126
+ body["ccAddresses"] = cc_addresses
127
+ if bcc_addresses is not None:
128
+ body["bccAddresses"] = bcc_addresses
129
+ if from_address is not None:
130
+ body["fromAddress"] = from_address
131
+ if personalization_values is not None:
132
+ body["personalizationValues"] = [
133
+ {
134
+ "name": key,
135
+ "value": value,
136
+ }
137
+ for key, value in personalization_values.items()
138
+ ]
139
+ if metadata is not None:
140
+ body["metadata"] = metadata
141
+ if attachments is not None:
142
+ body["attachments"] = [
143
+ {
144
+ "fileName": attachment.file_name,
145
+ "mimeType": attachment.mime_type,
146
+ "content": attachment.content,
147
+ }
148
+ for attachment in attachments
149
+ ]
150
+
151
+ response = requests.post(
152
+ url=f"https://{region}-api.dotdigital.com/v2/email/triggered-campaign",
153
+ json=body,
154
+ headers={
155
+ "accept": "text/plain",
156
+ "authorization": auth,
157
+ },
158
+ timeout=timeout,
159
+ )
160
+
161
+ assert response.ok, "Failed to send email." f" Reason: {response.reason}." f" Text: {response.text}."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 6.43.0
3
+ Version: 6.43.1
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.8
6
6
  Classifier: Framework :: Django
@@ -24,7 +24,7 @@ Requires-Dist: django-classy-tags ==2.0.0
24
24
  Requires-Dist: libsass ==0.23.0
25
25
  Requires-Dist: phonenumbers ==8.12.12
26
26
  Requires-Dist: more-itertools ==8.7.0
27
- Requires-Dist: cfl-common ==6.43.0
27
+ Requires-Dist: cfl-common ==6.43.1
28
28
  Requires-Dist: django-ratelimit ==3.0.1
29
29
  Requires-Dist: django-preventconcurrentlogins ==0.8.2
30
30
  Requires-Dist: django-csp ==3.7
@@ -5,14 +5,14 @@ cfl_common/common/app_settings.py,sha256=x2ROLY5Xl5LgqjxyTiChZvQorZYUXpFzEkaLsjh
5
5
  cfl_common/common/apps.py,sha256=49UXZ3bSkFKvIEOL4zM7y1sAhccQJyRtsoOg5XVd_8Y,129
6
6
  cfl_common/common/context_processors.py,sha256=X0iuX5qu9kMWa7q8osE9CJ2LgM7pPOYQFGdjm8X3rk0,236
7
7
  cfl_common/common/csp_config.py,sha256=sZT6s9zMT5FFIqNODsURT0ifxbDgXpDlki8UxaBq2iE,2940
8
- cfl_common/common/email_messages.py,sha256=DRiz6MCKUGdFsC-pN9EwFqzPhpzMWXaT9HPcji1BkvE,4437
9
- cfl_common/common/mail.py,sha256=5iwvedYfaJUv7v8vVpV1kyBtnw04EJhHPy3FRGI9WHM,4223
8
+ cfl_common/common/email_messages.py,sha256=oK8cb5wrDbxq6xoEoILHJggs3P35aEyk9eFJHIR6y74,3644
9
+ cfl_common/common/mail.py,sha256=qgsgBc0drFIG8ik4ZBjaqjSvk0LVDIJV2fNYWFrbzHU,5990
10
10
  cfl_common/common/models.py,sha256=EunFsc7sOWfWiFf4IQwuy56gu8pu3YpPoOgVtsMhbRM,14958
11
11
  cfl_common/common/permissions.py,sha256=gC6RQGZI2QDBbglx-xr_V4Hl2C2nf1V2_uPmEuoEcJo,2416
12
12
  cfl_common/common/utils.py,sha256=Nn2Npao9Uqad5Js_IdHwF-ow6wrPNpBLW4AO1LxoEBc,1727
13
13
  cfl_common/common/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  cfl_common/common/helpers/data_migration_loader.py,sha256=_BhS5lPmhcuVUbryBmJytlWdHyT02KYyxPkHar32mOE,1748
15
- cfl_common/common/helpers/emails.py,sha256=u2X2brjHIlUDNIgQ6-Ld23Y4zyouJGTFH-G7HNQDBYs,11041
15
+ cfl_common/common/helpers/emails.py,sha256=6xY8YxYY3ywcFWguys2G_36HTaBBah4ma1p20s4mpKU,10099
16
16
  cfl_common/common/helpers/generators.py,sha256=kTL5e91I8wgmjJ-mu4jr9vIacjccUZ5pZSAz5cUNhdM,1505
17
17
  cfl_common/common/helpers/organisation.py,sha256=e-JKumKoXrkMTzZPv0H4ViWL8vtCt7oXJjn_zZ1ec00,427
18
18
  cfl_common/common/migrations/0001_initial.py,sha256=Y2kt2xmdCbrmDXCgqmhXeacicNg26Zj7L7SANSsgAAI,9664
@@ -106,7 +106,7 @@ example_project/portal_test_settings.py,sha256=frp_XMpd-z1g3VFCRxB2w7AaFW2ivRVKn
106
106
  example_project/settings.py,sha256=XRZZvASoIl5a9xe3masTq_CUBleuJq9ByHx8f_e2UFc,5613
107
107
  example_project/urls.py,sha256=OVeRQ-TCpzHISBRuzqD0yd3ewF7H5U3c-f2p2alfUD0,430
108
108
  example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
109
- portal/__init__.py,sha256=QcuQSlJPY-R1FVgen2wz3xT3Zw5oZBeORJW5UieLYIU,23
109
+ portal/__init__.py,sha256=Ngar-CylGsb6FZcYQn3kMXH5BOJ1Ub5AefCQXyRW8-E,23
110
110
  portal/admin.py,sha256=k5Hsiln43DlVPoufnrx5AXWu_RijX8xi_n7wwBuuCJo,5132
111
111
  portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
112
112
  portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
@@ -548,7 +548,7 @@ portal/tests/test_independent_student.py,sha256=ysWpkYiwjPdB7gO3ow-5JuxqLi0IywRS
548
548
  portal/tests/test_invite_teacher.py,sha256=oeOaoJV1IqJSYPlaPFjnhVXdB2mq8otCTLp_lfjuCfk,12224
549
549
  portal/tests/test_middleware.py,sha256=b6jfNmiRZ2snqLKsyJUG-RivoX5fmrqLlQkG9MeVnqM,8034
550
550
  portal/tests/test_newsletter_footer.py,sha256=MdVUX53mEoDTa4Krq-jg9LFNo-QyghqvTvhHeNXBGnE,838
551
- portal/tests/test_organisation.py,sha256=fOtck-0MkPM2F0V4RFH-QUeWEk6yUIXDv_GI5cl8sdg,7649
551
+ portal/tests/test_organisation.py,sha256=kCMUNzLN6EzaMUBcFkqXwnqLGgOuQxQWIHHt63nhqBs,7574
552
552
  portal/tests/test_partials.py,sha256=ydh1nef6BqvMfah2BSBS9QDiKY0xopY74k_W1YVobAE,3687
553
553
  portal/tests/test_ratelimit.py,sha256=XWq1A9XgRrlcMHibGoJ0kc4gLc5U_u5UhKHjthxCfYA,19376
554
554
  portal/tests/test_school_student.py,sha256=bFZwY4twaFHQLp0cltMq8cLNDZGgCHTZBCZHK0JcV8s,8604
@@ -636,14 +636,14 @@ portal/views/student/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
636
636
  portal/views/student/edit_account_details.py,sha256=keMakqgqy5xB76QbpwsnkadxbMg_dGsAxLuP2CoWbvc,8551
637
637
  portal/views/student/play.py,sha256=-v9lBjHF3_PAKRgWcCGGt_bEOpIkmJDJnzgR5JvqrMo,8908
638
638
  portal/views/teacher/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
639
- portal/views/teacher/dashboard.py,sha256=_zKAEIaMwCI5LdF5QN2kLy59UTkNhNnx5mYhe-mfdVA,24991
639
+ portal/views/teacher/dashboard.py,sha256=nNA7XxylunLjyCpKmq7h_CYITi7wM3YnmjqzUL0A-bI,25236
640
640
  portal/views/teacher/teach.py,sha256=B71jReMJ4BYFmo7NtJVK3-4DeXEwxfu_WA3Ij1RYzdI,34725
641
641
  portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
642
642
  portal/views/two_factor/core.py,sha256=O_wcBeFqdPYSGNGv-pT_vbs5-Dj1Z-Jfkd6f9-E5yZI,760
643
643
  portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
644
644
  portal/views/two_factor/profile.py,sha256=tkl_ludo8arMtd5LKNmohM66vpC_YQiP-0nspTSJiJ4,383
645
- codeforlife_portal-6.43.0.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
646
- codeforlife_portal-6.43.0.dist-info/METADATA,sha256=YnRGpJH354nDAr6qgrjVk7parxVg530N5gvYp6EtDNk,1137
647
- codeforlife_portal-6.43.0.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
648
- codeforlife_portal-6.43.0.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
649
- codeforlife_portal-6.43.0.dist-info/RECORD,,
645
+ codeforlife_portal-6.43.1.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
646
+ codeforlife_portal-6.43.1.dist-info/METADATA,sha256=tFzxDaekn6AVyuunmE_TYU1KveLBu1erHq8KPawpbzs,1137
647
+ codeforlife_portal-6.43.1.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
648
+ codeforlife_portal-6.43.1.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
649
+ codeforlife_portal-6.43.1.dist-info/RECORD,,
portal/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "6.43.0"
1
+ __version__ = "6.43.1"
@@ -4,9 +4,11 @@ import time
4
4
 
5
5
  from common.models import Teacher
6
6
  from common.tests.utils.classes import create_class_directly
7
- from common.tests.utils.organisation import (create_organisation,
8
- create_organisation_directly,
9
- join_teacher_to_organisation)
7
+ from common.tests.utils.organisation import (
8
+ create_organisation,
9
+ create_organisation_directly,
10
+ join_teacher_to_organisation,
11
+ )
10
12
  from common.tests.utils.student import create_school_student_directly
11
13
  from common.tests.utils.teacher import signup_teacher_directly
12
14
  from selenium.webdriver.common.by import By
@@ -2,12 +2,24 @@ from datetime import timedelta
2
2
  from uuid import uuid4
3
3
 
4
4
  from common import email_messages
5
- from common.helpers.emails import (INVITE_FROM, NOTIFICATION_EMAIL,
6
- DotmailerUserType, add_to_dotmailer,
7
- generate_token, send_email, update_email)
5
+ from common.helpers.emails import (
6
+ INVITE_FROM,
7
+ NOTIFICATION_EMAIL,
8
+ DotmailerUserType,
9
+ add_to_dotmailer,
10
+ generate_token,
11
+ send_email,
12
+ update_email,
13
+ )
8
14
  from common.helpers.generators import get_random_username
9
- from common.models import (Class, JoinReleaseStudent, SchoolTeacherInvitation,
10
- Student, Teacher)
15
+ from common.mail import campaign_ids, send_dotdigital_email
16
+ from common.models import (
17
+ Class,
18
+ JoinReleaseStudent,
19
+ SchoolTeacherInvitation,
20
+ Student,
21
+ Teacher,
22
+ )
11
23
  from common.permissions import check_teacher_authorised, logged_in_as_teacher
12
24
  from common.utils import using_two_factor
13
25
  from django.contrib import messages as messages
@@ -16,7 +28,7 @@ from django.contrib.auth.decorators import login_required, user_passes_test
16
28
  from django.contrib.auth.models import User
17
29
  from django.http import Http404, HttpResponseRedirect
18
30
  from django.shortcuts import get_object_or_404, render
19
- from django.urls import reverse_lazy
31
+ from django.urls import reverse, reverse_lazy
20
32
  from django.utils import timezone
21
33
  from django.views.decorators.http import require_POST
22
34
  from game.level_management import levels_shared_with, unshare_level
@@ -25,14 +37,20 @@ from two_factor.utils import devices_for_user
25
37
  from portal.forms.invite_teacher import InviteTeacherForm
26
38
  from portal.forms.organisation import OrganisationForm
27
39
  from portal.forms.registration import DeleteAccountForm
28
- from portal.forms.teach import (ClassCreationForm, InvitedTeacherForm,
29
- TeacherAddExternalStudentForm,
30
- TeacherEditAccountForm)
40
+ from portal.forms.teach import (
41
+ ClassCreationForm,
42
+ InvitedTeacherForm,
43
+ TeacherAddExternalStudentForm,
44
+ TeacherEditAccountForm,
45
+ )
31
46
  from portal.helpers.decorators import ratelimit
32
47
  from portal.helpers.password import check_update_password
33
- from portal.helpers.ratelimit import (RATELIMIT_LOGIN_GROUP,
34
- RATELIMIT_LOGIN_RATE, RATELIMIT_METHOD,
35
- clear_ratelimit_cache_for_user)
48
+ from portal.helpers.ratelimit import (
49
+ RATELIMIT_LOGIN_GROUP,
50
+ RATELIMIT_LOGIN_RATE,
51
+ RATELIMIT_METHOD,
52
+ clear_ratelimit_cache_for_user,
53
+ )
36
54
 
37
55
  from .teach import create_class
38
56
 
@@ -380,19 +398,22 @@ def invite_toggle_admin(request, invite_id):
380
398
 
381
399
  if invite.invited_teacher_is_admin:
382
400
  messages.success(request, "Administrator invite status has been given successfully")
383
- emailMessage = email_messages.adminGivenEmail(request, invite.school)
401
+ send_dotdigital_email(
402
+ campaign_ids["admin_given"],
403
+ [invite.invited_teacher_email],
404
+ personalization_values={
405
+ "SCHOOL_CLUB_NAME": invite.school,
406
+ "MANAGEMENT_LINK": request.build_absolute_uri(reverse("dashboard")),
407
+ },
408
+ )
384
409
 
385
410
  else:
386
411
  messages.success(request, "Administrator invite status has been revoked successfully")
387
- emailMessage = email_messages.adminRevokedEmail(request, invite.school)
388
-
389
- send_email(
390
- NOTIFICATION_EMAIL,
391
- [invite.invited_teacher_email],
392
- emailMessage["subject"],
393
- emailMessage["message"],
394
- emailMessage["subject"],
395
- )
412
+ send_dotdigital_email(
413
+ campaign_ids["admin_revoked"],
414
+ [invite.invited_teacher_email],
415
+ personalization_values={"SCHOOL_CLUB_NAME": invite.school},
416
+ )
396
417
 
397
418
  return HttpResponseRedirect(reverse_lazy("dashboard"))
398
419
 
@@ -411,7 +432,14 @@ def organisation_toggle_admin(request, pk):
411
432
 
412
433
  if teacher.is_admin:
413
434
  messages.success(request, "Administrator status has been given successfully.")
414
- email_message = email_messages.adminGivenEmail(request, teacher.school.name)
435
+ send_dotdigital_email(
436
+ campaign_ids["admin_given"],
437
+ [teacher.new_user.email],
438
+ personalization_values={
439
+ "SCHOOL_CLUB_NAME": teacher.school.name,
440
+ "MANAGEMENT_LINK": request.build_absolute_uri(reverse("dashboard")),
441
+ },
442
+ )
415
443
  else:
416
444
  # Remove access to all levels that are from other teachers' students
417
445
  [
@@ -420,15 +448,11 @@ def organisation_toggle_admin(request, pk):
420
448
  if hasattr(level.owner, "student") and not teacher.teaches(level.owner)
421
449
  ]
422
450
  messages.success(request, "Administrator status has been revoked successfully.")
423
- email_message = email_messages.adminRevokedEmail(request, teacher.school.name)
424
-
425
- send_email(
426
- NOTIFICATION_EMAIL,
427
- [teacher.new_user.email],
428
- email_message["subject"],
429
- email_message["message"],
430
- email_message["subject"],
431
- )
451
+ send_dotdigital_email(
452
+ campaign_ids["admin_revoked"],
453
+ [teacher.new_user.email],
454
+ personalization_values={"SCHOOL_CLUB_NAME": teacher.school.name},
455
+ )
432
456
 
433
457
  return HttpResponseRedirect(reverse_lazy("dashboard"))
434
458