Skip to content

Commit 1608291

Browse files
committed
emails: add test command & update backend, config
Bug: T412427
1 parent bd30153 commit 1608291

File tree

10 files changed

+88
-14
lines changed

10 files changed

+88
-14
lines changed

TWLight/emails/backends/mediawiki.py

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def conn(*args, **kwargs):
4141
logger.warning("ConnectionError exhausted retries")
4242
raise e
4343
logger.warning(
44-
"ConnectionError, retrying in {self.retry_after_conn}s"
44+
"ConnectionError, retrying in {}s".format(self.retry_after_conn)
4545
)
4646
sleep(retry_after_conn)
4747
continue
@@ -56,20 +56,20 @@ def _handle_maxlag(response):
5656
data = response.json()
5757
try:
5858
if data["error"]["code"] != "maxlag":
59-
return data
59+
return response
6060
except KeyError:
61-
return data
61+
return response
6262

6363
retry_after = float(response.headers.get("Retry-After", 5))
6464
retry_on_lag_error = 50
6565
no_retry = 0 <= retry_on_lag_error < try_count
6666

6767
message = "Server exceeded maxlag"
6868
if not no_retry:
69-
message += f", retrying in {retry_after}s"
69+
message += ", retrying in {}s".format(retry_after)
7070
if "lag" in data["error"]:
71-
message += f", lag={data['error']['lag']}"
72-
message += f", API={self.url}"
71+
message += ", lag={}".format(data["error"]["lag"])
72+
message += ", API=".format(self.url)
7373

7474
log = logger.warning if no_retry else logger.info
7575
log(
@@ -117,6 +117,7 @@ def __init__(
117117
self.email_token = None
118118
self.session = None
119119
self._lock = RLock()
120+
logger.info("Email connection constructed.")
120121

121122
def open(self):
122123
"""
@@ -164,15 +165,26 @@ def open(self):
164165
raise Exception("There was an error in the request for the login.")
165166

166167
# GET request to fetch Email token
168+
# see: https://www.mediawiki.org/wiki/API:Emailuser#Token
167169
email_token_params = {"action": "query", "meta": "tokens", "format": "json"}
168170

169171
logger.info("Getting email token...")
170172
email_token_response = session.get(url=self.url, params=email_token_params)
173+
if email_token_response.status_code != 200:
174+
raise Exception(
175+
"There was an error in the request for the email token."
176+
)
177+
171178
email_token_data = email_token_response.json()
172179

180+
email_token = email_token_data["query"]["tokens"]["csrftoken"]
181+
if not email_token:
182+
raise Exception("There was an error obtaining the email token.")
183+
173184
# Assign the session and email token
174-
self.email_token = email_token_data["query"]["tokens"]["csrftoken"]
185+
self.email_token = email_token
175186
self.session = session
187+
logger.info("Email API session ready.")
176188
return True
177189
except:
178190
if not self.fail_silently:
@@ -232,10 +244,10 @@ def _send(self, email_message):
232244
emailable_response = self.session.post(
233245
url=self.url, data=emailable_params
234246
)
235-
logger.info(emailable_response.text)
236247
emailable_data = emailable_response.json()
237248
emailable = "emailable" in emailable_data["query"]["users"][0]
238249
if not emailable:
250+
logger.warning("User not emailable, email skipped.")
239251
continue
240252

241253
# POST request to send an email
@@ -250,12 +262,17 @@ def _send(self, email_message):
250262
}
251263

252264
logger.info("Sending email...")
253-
emailuser_data = _handle_maxlag(
265+
emailuser_response = _handle_maxlag(
254266
self.session.post(url=self.url, data=email_params)
255267
)
256-
logger.info(emailuser_data)
268+
if emailuser_response.status_code != 200:
269+
raise Exception(
270+
"There was an error in the request to send the email."
271+
)
272+
emailuser_data = emailuser_response.json()
257273
if emailuser_data["emailuser"]["result"] != "Success":
258274
raise Exception("There was an error when trying to send the email.")
275+
logger.info("Email sent.")
259276
except:
260277
if not self.fail_silently:
261278
raise

TWLight/emails/tasks.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"""
2424

2525
from djmail import template_mail
26+
from djmail.models import Message
2627
from djmail.template_mail import MagicMailBuilder, InlineCSSTemplateMail
2728
import logging
2829
import os
@@ -31,6 +32,7 @@
3132
from django_comments.models import Comment
3233
from django_comments.signals import comment_was_posted
3334
from django.contrib.sites.shortcuts import get_current_site
35+
from django.core.mail import get_connection
3436
from django.urls import reverse_lazy
3537
from django.db.models.signals import pre_save
3638
from django.dispatch import receiver
@@ -40,8 +42,7 @@
4042
from TWLight.applications.signals import Reminder
4143
from TWLight.resources.models import AccessCode, Partner
4244
from TWLight.users.groups import get_restricted
43-
from TWLight.users.signals import Notice, Survey, UserLoginRetrieval
44-
45+
from TWLight.users.signals import Notice, Survey, TestEmail, UserLoginRetrieval
4546

4647
logger = logging.getLogger(__name__)
4748

@@ -74,6 +75,10 @@ class SurveyActiveUser(template_mail.TemplateMail):
7475
name = "survey_active_user"
7576

7677

78+
class Test(template_mail.TemplateMail):
79+
name = "test"
80+
81+
7782
class CoordinatorReminderNotification(template_mail.TemplateMail):
7883
name = "coordinator_reminder_notification"
7984

@@ -203,6 +208,17 @@ def send_survey_active_user_emails(sender, **kwargs):
203208
)
204209

205210

211+
@receiver(TestEmail.test)
212+
def send_test(sender, **kwargs):
213+
email = kwargs["email"]
214+
connection = get_connection(
215+
backend="TWLight.emails.backends.mediawiki.EmailBackend"
216+
)
217+
template_email = Test()
218+
email = template_email.make_email_object(email, {}, connection=connection)
219+
email.send()
220+
221+
206222
@receiver(comment_was_posted)
207223
def send_comment_notification_emails(sender, **kwargs):
208224
"""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>Please disregard this message; this is only a test</p>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Please disregard this message; this is only a test
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test message; please disregard

TWLight/settings/base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,13 @@ def show_toolbar(request):
419419
# ------------------------------------------------------------------------------
420420

421421
TWLIGHT_API_PROVIDER_ENDPOINT = os.environ.get("TWLIGHT_API_PROVIDER_ENDPOINT", None)
422+
MW_API_URL = os.environ.get("MW_API_URL", None)
423+
MW_API_REQUEST_TIMEOUT = os.environ.get("MW_API_REQUEST_TIMEOUT", 60)
424+
MW_API_REQUEST_DELAY = os.environ.get("MW_API_REQUEST_DELAY", 0)
425+
MW_API_REQUEST_RETRY_DELAY = os.environ.get("MW_API_REQUEST_RETRY_DELAY", 5)
426+
MW_API_MAXLAG = os.environ.get("MW_API_MAXLAG", 5)
427+
MW_API_EMAIL_USER = os.environ.get("MW_API_EMAIL_USER", None)
428+
MW_API_EMAIL_PASSWORD = os.environ.get("MW_API_EMAIL_PASSWORD", None)
422429

423430
# COMMENTS CONFIGURATION
424431
# ------------------------------------------------------------------------------
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- coding: utf-8 -*-
2+
from django.contrib.auth.models import User
3+
from django.core.management.base import BaseCommand
4+
5+
from TWLight.users.signals import TestEmail
6+
7+
8+
class Command(BaseCommand):
9+
help = "Sends testmail to a wikipedia editor."
10+
11+
def add_arguments(self, parser):
12+
parser.add_argument('wp_username', type=str, help='The wikipedia editor to send the test email to')
13+
14+
def handle(self, *args, **options):
15+
user = User.objects.select_related("editor").get(editor__wp_username=options["wp_username"])
16+
TestEmail.test.send(
17+
sender=self.__class__,
18+
wp_username=user.editor.wp_username,
19+
email=user.email,
20+
)

TWLight/users/signals.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ class Survey(object):
2929
survey_active_user = Signal()
3030

3131

32+
class TestEmail(object):
33+
test = Signal()
34+
35+
3236
class UserLoginRetrieval(object):
3337
user_retrieve_monthly_logins = Signal()
3438

conf/local.twlight.env

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
DJANGO_DB_HOST=db
2-
DJANGO_EMAIL_BACKEND=django_dkim.backends.console.EmailBackend
2+
#DJANGO_EMAIL_BACKEND=TWLight.emails.backends.mediawiki.EmailBackend
3+
DJANGO_EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
34
DJANGO_EMAIL_ADMINS_BACKEND=django.core.mail.backends.dummy.EmailBackend
45
DKIM_SELECTOR=local
56
DKIM_DOMAIN=localhost
@@ -19,5 +20,6 @@ DEBUG=True
1920
TWLIGHT_OAUTH_PROVIDER_URL=https://meta.wikimedia.org/w/index.php
2021
TWLIGHT_API_PROVIDER_ENDPOINT=https://meta.wikimedia.org/w/api.php
2122
TWLIGHT_EZPROXY_URL=https://ezproxy.dev.localdomain:2443
23+
MW_API_URL=http://host.docker.internal:8080/w/api.php
2224
# seeem to be having troubles with --workers > 1
2325
GUNICORN_CMD_ARGS=--name twlight --workers 1 --backlog 2048 --timeout 300 --bind=0.0.0.0:80 --forwarded-allow-ips * --reload --log-level=info

docker-compose.override.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ secrets:
2525

2626
services:
2727
twlight:
28+
extra_hosts:
29+
- "host.docker.internal:host-gateway"
2830
image: quay.io/wikipedialibrary/twlight:local
2931
env_file:
30-
- ./conf/local.twlight.env
32+
- path: ./conf/local.twlight.env
33+
required: true
34+
- path: .env
35+
required: false
3136
# Local environment should mount things from the code directory
3237
volumes:
3338
- type: bind

0 commit comments

Comments
 (0)