-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Sends emails to users who have a Marker with send_welcome_email set to True. This is an improvement on the previous send_password_reset_emails as it makes it more explicit who should be getting emails, and can also send emails to already registered users, who get a slightly different email. Also enables restriction by stage and marking session as an extra safeguard Fixes #183
- Loading branch information
Showing
4 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
[ | ||
{ | ||
"model": "auth.user", | ||
"pk": 101, | ||
"fields": { | ||
"password": "thisisasecret", | ||
"last_login": null, | ||
"is_superuser": true, | ||
"username": "already_registered", | ||
"first_name": "", | ||
"last_name": "", | ||
"email": "[email protected]", | ||
"is_staff": false, | ||
"is_active": true, | ||
"date_joined": "2022-12-19T13:40:36.075Z", | ||
"groups": [], | ||
"user_permissions": [] | ||
} | ||
}, | ||
{ | ||
"model": "auth.user", | ||
"pk": 102, | ||
"fields": { | ||
"password": "", | ||
"last_login": null, | ||
"is_superuser": false, | ||
"username": "new_marker", | ||
"first_name": "Anew", | ||
"last_name": "Marker", | ||
"email": "[email protected]", | ||
"is_staff": false, | ||
"is_active": true, | ||
"date_joined": "2022-12-19T13:40:36.075Z", | ||
"groups": [], | ||
"user_permissions": [] | ||
} | ||
}, | ||
{ | ||
"model": "crowdsourcer.marker", | ||
"pk": 101, | ||
"fields": { | ||
"user_id": 101, | ||
"response_type_id": 1, | ||
"authority_id": 2, | ||
"send_welcome_email": true, | ||
"marking_session": [1] | ||
} | ||
}, | ||
{ | ||
"model": "crowdsourcer.marker", | ||
"pk": 102, | ||
"fields": { | ||
"user_id": 102, | ||
"response_type_id": 1, | ||
"send_welcome_email": true, | ||
"marking_session": [1] | ||
} | ||
} | ||
] |
105 changes: 105 additions & 0 deletions
105
crowdsourcer/management/commands/send_welcome_emails.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
from time import sleep | ||
|
||
from django.contrib.auth.forms import PasswordResetForm | ||
from django.core.management.base import BaseCommand | ||
from django.http import HttpRequest | ||
from django.utils.crypto import get_random_string | ||
|
||
from crowdsourcer.models import Marker, MarkingSession, ResponseType | ||
|
||
YELLOW = "\033[33m" | ||
NOBOLD = "\033[0m" | ||
|
||
|
||
class Command(BaseCommand): | ||
help = "Emails password reset instructions to all users" | ||
|
||
new_user_template = "registration/initial_password_email.html" | ||
previous_user_template = "registration/repeat_password_email.html" | ||
|
||
def add_arguments(self, parser): | ||
parser.add_argument("--send_emails", action="store_true", help="Send emails") | ||
|
||
parser.add_argument( | ||
"--stage", action="store", help="Only send emails to people in this stage" | ||
) | ||
|
||
parser.add_argument( | ||
"--session", | ||
action="store", | ||
help="Only send emails to people in this session", | ||
) | ||
|
||
def handle(self, *args, **kwargs): | ||
if not kwargs["send_emails"]: | ||
self.stdout.write( | ||
f"{YELLOW}Not sending emails. Call with --send_emails to send{NOBOLD}" | ||
) | ||
|
||
users = Marker.objects.filter(send_welcome_email=True).select_related("user") | ||
|
||
if kwargs["stage"]: | ||
try: | ||
rt = ResponseType.objects.get(type=kwargs["stage"]) | ||
users = users.filter(response_type=rt) | ||
except ResponseType.NotFoundException: | ||
self.stderr.write(f"{YELLOW}No such stage: {kwargs['stage']}{NOBOLD}") | ||
return | ||
|
||
if kwargs["session"]: | ||
try: | ||
rt = MarkingSession.objects.get(label=kwargs["session"]) | ||
users = users.filter(marking_session=rt) | ||
except ResponseType.NotFoundException: | ||
self.stderr.write( | ||
f"{YELLOW}No such session: {kwargs['session']}{NOBOLD}" | ||
) | ||
return | ||
|
||
user_count = users.count() | ||
self.stdout.write(f"Sending emails for {user_count} users") | ||
count = 0 | ||
for marker in users: | ||
user = marker.user | ||
try: | ||
if user.email: | ||
self.stdout.write(f"Sending email for to this email: {user.email}") | ||
if kwargs["send_emails"]: | ||
template = self.new_user_template | ||
if user.password == "": | ||
user.set_password(get_random_string(length=20)) | ||
user.save() | ||
else: | ||
template = self.previous_user_template | ||
|
||
form = PasswordResetForm({"email": user.email}) | ||
assert form.is_valid() | ||
request = HttpRequest() | ||
request.META["SERVER_NAME"] = ( | ||
"marking.councilclimatescorecards.uk" | ||
) | ||
request.META["SERVER_PORT"] = 443 | ||
form.save( | ||
request=request, | ||
domain_override="marking.councilclimatescorecards.uk", | ||
use_https=True, | ||
from_email="CEUK Scorecards Marking <[email protected]>", | ||
subject_template_name="registration/initial_password_email_subject.txt", | ||
email_template_name=template, | ||
) | ||
marker.send_welcome_email = False | ||
marker.save() | ||
sleep(1) | ||
count = count + 1 | ||
except Exception as e: | ||
print(e) | ||
continue | ||
|
||
if kwargs["send_emails"]: | ||
self.stdout.write(f"Sent {count} emails") | ||
else: | ||
self.stdout.write( | ||
f"{YELLOW}Dry Run{NOBOLD}. Live would have sent {count} emails" | ||
) | ||
|
||
return "done" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
from unittest import skip | ||
|
||
from django.contrib.auth.models import User | ||
from django.core import mail | ||
from django.core.management import call_command | ||
from django.test import TestCase | ||
|
||
|
@@ -516,3 +517,93 @@ def test_multiple_choice_question(self): | |
self.assertIsNotNone(r.multi_option) | ||
|
||
self.assertEquals(r.multi_option.all()[0].description, "Car share") | ||
|
||
|
||
class SendWelcomeEmails(BaseCommandTestCase): | ||
fixtures = [ | ||
"basics.json", | ||
"authorities.json", | ||
"users.json", | ||
"welcome_email_users.json", | ||
] | ||
|
||
def test_basic_run(self): | ||
self.assertEquals(len(mail.outbox), 0) | ||
self.call_command( | ||
"send_welcome_emails", | ||
) | ||
self.assertEquals(len(mail.outbox), 0) | ||
|
||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
) | ||
self.assertEquals(len(mail.outbox), 2) | ||
|
||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
) | ||
self.assertEquals(len(mail.outbox), 2) | ||
|
||
def test_only_sends_if_flag_set(self): | ||
marker = Marker.objects.get(user__email="[email protected]") | ||
marker.send_welcome_email = False | ||
marker.save() | ||
|
||
self.assertEquals(len(mail.outbox), 0) | ||
|
||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
) | ||
self.assertEquals(len(mail.outbox), 1) | ||
email = mail.outbox[0] | ||
self.assertEquals(email.to, ["[email protected]"]) | ||
|
||
def test_email_comtent(self): | ||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
) | ||
|
||
emails = mail.outbox | ||
|
||
text = "your previous password" | ||
for m in emails: | ||
if m.to[0] == "[email protected]": | ||
self.assertTrue(m.body.rfind(text) >= 0) | ||
else: | ||
self.assertTrue(m.body.rfind(text) == -1) | ||
|
||
def test_limit_stage(self): | ||
self.assertEquals(len(mail.outbox), 0) | ||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
stage="Audit", | ||
) | ||
self.assertEquals(len(mail.outbox), 0) | ||
|
||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
stage="First Mark", | ||
) | ||
self.assertEquals(len(mail.outbox), 2) | ||
|
||
def test_limit_session(self): | ||
self.assertEquals(len(mail.outbox), 0) | ||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
session="Second Session", | ||
) | ||
self.assertEquals(len(mail.outbox), 0) | ||
|
||
self.call_command( | ||
"send_welcome_emails", | ||
send_emails=True, | ||
session="Default", | ||
) | ||
self.assertEquals(len(mail.outbox), 2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{% autoescape off %} | ||
Hi, | ||
|
||
You're receiving this email because you registered to volunteer for the CEUK Council Climate Scorecards. This email allows you to log into the online data collection system that we will use to score Councils. | ||
|
||
If you can remember your previous password from the 2023 Scorecards then you can log in with your username at | ||
|
||
{{ protocol }}://{{ domain }} | ||
|
||
If you cannot remember your password then please go to the following page and choose a new password: | ||
{% block reset_link %} | ||
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} | ||
{% endblock %} | ||
|
||
Your username is {{ user.get_username }} | ||
|
||
Thanks for volunteering! | ||
|
||
The CEUK team. | ||
|
||
{% endautoescape %} | ||
|