Skip to content

Commit d4cfdf3

Browse files
committed
Send tags header to mandrill
1 parent a3a53e9 commit d4cfdf3

14 files changed

+76
-21
lines changed

Diff for: h/emails/flag_notification.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pyramid.renderers import render
22

33
from h.i18n import TranslationString as _
4+
from h.services.email import EmailTag
45

56

67
def generate(request, email, incontext_link):
@@ -27,4 +28,4 @@ def generate(request, email, incontext_link):
2728
"h:templates/emails/flag_notification.html.jinja2", context, request=request
2829
)
2930

30-
return [email], subject, text, html
31+
return [email], subject, text, EmailTag.FLAG_NOTIFICATION, html

Diff for: h/emails/reply_notification.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from h.models import Subscriptions
66
from h.notification.reply import Notification
77
from h.services import SubscriptionService
8+
from h.services.email import EmailTag
89

910

1011
def generate(request: Request, notification: Notification):
@@ -49,7 +50,13 @@ def generate(request: Request, notification: Notification):
4950
"h:templates/emails/reply_notification.html.jinja2", context, request=request
5051
)
5152

52-
return [notification.parent_user.email], subject, text, html
53+
return (
54+
[notification.parent_user.email],
55+
subject,
56+
text,
57+
EmailTag.REPLY_NOTIFICATION,
58+
html,
59+
)
5360

5461

5562
def _get_user_url(user, request):

Diff for: h/emails/reset_password.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pyramid.renderers import render
22

33
from h.i18n import TranslationString as _
4+
from h.services.email import EmailTag
45

56

67
def generate(request, user):
@@ -31,4 +32,4 @@ def generate(request, user):
3132
"h:templates/emails/reset_password.html.jinja2", context, request=request
3233
)
3334

34-
return [user.email], subject, text, html
35+
return [user.email], subject, text, EmailTag.RESET_PASSWORD, html

Diff for: h/emails/signup.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pyramid.renderers import render
22

33
from h.i18n import TranslationString as _
4+
from h.services.email import EmailTag
45

56

67
def generate(request, user_id, email, activation_code):
@@ -27,4 +28,4 @@ def generate(request, user_id, email, activation_code):
2728
text = render("h:templates/emails/signup.txt.jinja2", context, request=request)
2829
html = render("h:templates/emails/signup.html.jinja2", context, request=request)
2930

30-
return [email], subject, text, html
31+
return [email], subject, text, EmailTag.ACTIVATION, html

Diff for: h/emails/test.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pyramid.renderers import render
55

66
from h import __version__
7+
from h.services.email import EmailTag
78

89

910
def generate(request, recipient):
@@ -28,4 +29,4 @@ def generate(request, recipient):
2829
text = render("h:templates/emails/test.txt.jinja2", context, request=request)
2930
html = render("h:templates/emails/test.html.jinja2", context, request=request)
3031

31-
return [recipient], "Test mail", text, html
32+
return [recipient], "Test mail", text, EmailTag.TEST, html

Diff for: h/services/email.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# noqa: A005
22

33
import smtplib
4+
from enum import StrEnum
45

56
import pyramid_mailer
67
import pyramid_mailer.message
@@ -12,6 +13,14 @@
1213
logger = get_task_logger(__name__)
1314

1415

16+
class EmailTag(StrEnum):
17+
ACTIVATION = "activation"
18+
FLAG_NOTIFICATION = "flag_notification"
19+
REPLY_NOTIFICATION = "reply_notification"
20+
RESET_PASSWORD = "reset_password" # noqa: S105
21+
TEST = "test"
22+
23+
1524
class EmailService:
1625
"""A service for sending emails."""
1726

@@ -20,10 +29,20 @@ def __init__(self, request: Request, mailer: IMailer) -> None:
2029
self._mailer = mailer
2130

2231
def send(
23-
self, recipients: list[str], subject: str, body: str, html: str | None = None
24-
):
32+
self,
33+
recipients: list[str],
34+
subject: str,
35+
body: str,
36+
tag: EmailTag,
37+
html: str | None = None,
38+
) -> None:
39+
extra_headers = {"X-MC-Tags": tag}
2540
email = pyramid_mailer.message.Message(
26-
subject=subject, recipients=recipients, body=body, html=html
41+
subject=subject,
42+
recipients=recipients,
43+
body=body,
44+
html=html,
45+
extra_headers=extra_headers,
2746
)
2847
if self._request.debug: # pragma: no cover
2948
logger.info("emailing in debug mode: check the `mail/` directory")

Diff for: h/tasks/mailer.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@
66

77
import smtplib
88

9-
from h.services.email import EmailService
9+
from h.services.email import EmailService, EmailTag
1010
from h.tasks.celery import celery
1111

1212
__all__ = ("send",)
1313

1414

1515
@celery.task(bind=True, max_retries=3, acks_late=True)
16-
def send(self, recipients, subject, body, html=None):
16+
def send( # noqa: PLR0913
17+
self,
18+
recipients: list[str],
19+
subject: str,
20+
body: str,
21+
tag: EmailTag,
22+
html: str | None = None,
23+
) -> None:
1724
"""
1825
Send an email.
1926
@@ -28,7 +35,9 @@ def send(self, recipients, subject, body, html=None):
2835
"""
2936
service = celery.request.find_service(EmailService)
3037
try:
31-
service.send(recipients=recipients, subject=subject, body=body, html=html)
38+
service.send(
39+
recipients=recipients, subject=subject, body=body, html=html, tag=tag
40+
)
3241
except smtplib.socket.error as exc:
3342
# Exponential backoff in case the SMTP service is having problems.
3443
countdown = self.default_retry_delay * 2**self.request.retries

Diff for: tests/unit/h/emails/flag_notification_test.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from h.emails.flag_notification import generate
4+
from h.services.email import EmailTag
45

56

67
class TestGenerate:
@@ -23,7 +24,7 @@ def test_appropriate_return_values(
2324
html_renderer.string_response = "HTML output"
2425
text_renderer.string_response = "Text output"
2526

26-
recipients, subject, text, html = generate(
27+
recipients, subject, text, tag, html = generate(
2728
pyramid_request,
2829
2930
incontext_link="http://hyp.is/a/ann1",
@@ -32,6 +33,7 @@ def test_appropriate_return_values(
3233
assert recipients == ["[email protected]"]
3334
assert subject == "An annotation has been flagged"
3435
assert html == "HTML output"
36+
assert tag == EmailTag.FLAG_NOTIFICATION
3537
assert text == "Text output"
3638

3739
@pytest.fixture

Diff for: tests/unit/h/emails/reply_notification_test.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def test_supports_non_ascii_display_names(
9999
parent_user.display_name = "Parent 👩"
100100
reply_user.display_name = "Child 👧"
101101

102-
(_, subject, _, _) = generate(pyramid_request, notification)
102+
(_, subject, _, _, _) = generate(pyramid_request, notification)
103103

104104
assert subject == "Child 👧 has replied to your annotation"
105105

@@ -130,28 +130,28 @@ def test_returns_text_and_body_results_from_renderers(
130130
html_renderer.string_response = "HTML output"
131131
text_renderer.string_response = "Text output"
132132

133-
_, _, text, html = generate(pyramid_request, notification)
133+
_, _, text, _, html = generate(pyramid_request, notification)
134134

135135
assert html == "HTML output"
136136
assert text == "Text output"
137137

138138
def test_returns_subject_with_reply_display_name(
139139
self, notification, pyramid_request
140140
):
141-
_, subject, _, _ = generate(pyramid_request, notification)
141+
_, subject, _, _, _ = generate(pyramid_request, notification)
142142

143143
assert subject == "Ron Burgundy has replied to your annotation"
144144

145145
def test_returns_subject_with_reply_username(
146146
self, notification, pyramid_request, reply_user
147147
):
148148
reply_user.display_name = None
149-
_, subject, _, _ = generate(pyramid_request, notification)
149+
_, subject, _, _, _ = generate(pyramid_request, notification)
150150

151151
assert subject == "ron has replied to your annotation"
152152

153153
def test_returns_parent_email_as_recipients(self, notification, pyramid_request):
154-
recipients, _, _, _ = generate(pyramid_request, notification)
154+
recipients, _, _, _, _ = generate(pyramid_request, notification)
155155

156156
assert recipients == ["[email protected]"]
157157

Diff for: tests/unit/h/emails/reset_password_test.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44

55
from h.emails.reset_password import generate
6+
from h.services.email import EmailTag
67

78

89
@pytest.mark.usefixtures("routes")
@@ -38,11 +39,12 @@ def test_appropriate_return_values(
3839
html_renderer.string_response = "HTML output"
3940
text_renderer.string_response = "Text output"
4041

41-
recipients, subject, text, html = generate(pyramid_request, user)
42+
recipients, subject, text, tag, html = generate(pyramid_request, user)
4243

4344
assert recipients == [user.email]
4445
assert subject == "Reset your password"
4546
assert html == "HTML output"
47+
assert tag == EmailTag.RESET_PASSWORD
4648
assert text == "Text output"
4749

4850
def test_jinja_templates_render(

Diff for: tests/unit/h/emails/signup_test.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from h.emails.signup import generate
4+
from h.services.email import EmailTag
45

56

67
@pytest.mark.usefixtures("routes")
@@ -27,7 +28,7 @@ def test_appropriate_return_values(
2728
html_renderer.string_response = "HTML output"
2829
text_renderer.string_response = "Text output"
2930

30-
recipients, subject, text, html = generate(
31+
recipients, subject, text, tag, html = generate(
3132
pyramid_request,
3233
user_id=1234,
3334
@@ -37,6 +38,7 @@ def test_appropriate_return_values(
3738
assert recipients == ["[email protected]"]
3839
assert subject == "Please activate your account"
3940
assert html == "HTML output"
41+
assert tag == EmailTag.ACTIVATION
4042
assert text == "Text output"
4143

4244
def test_jinja_templates_render(self, pyramid_config, pyramid_request):

Diff for: tests/unit/h/emails/test_test.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from h import __version__
55
from h.emails.test import generate
6+
from h.services.email import EmailTag
67

78

89
class TestGenerate:
@@ -26,13 +27,14 @@ def test_appropriate_return_values(
2627
html_renderer.string_response = "HTML output"
2728
text_renderer.string_response = "Text output"
2829

29-
recipients, subject, text, html = generate(
30+
recipients, subject, text, tag, html = generate(
3031
pyramid_request, "[email protected]"
3132
)
3233

3334
assert recipients == ["[email protected]"]
3435
assert subject == "Test mail"
3536
assert html == "HTML output"
37+
assert tag == EmailTag.TEST
3638
assert text == "Text output"
3739

3840
def test_jinja_templates_render(self, pyramid_config, pyramid_request):

Diff for: tests/unit/h/services/email_test.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import pytest
55

6-
from h.services.email import EmailService, factory
6+
from h.services.email import EmailService, EmailTag, factory
77

88

99
class TestEmailService:
@@ -12,13 +12,15 @@ def test_send_creates_email_message(self, email_service, pyramid_mailer):
1212
recipients=["[email protected]"],
1313
subject="My email subject",
1414
body="Some text body",
15+
tag=EmailTag.TEST,
1516
)
1617

1718
pyramid_mailer.message.Message.assert_called_once_with(
1819
recipients=["[email protected]"],
1920
subject="My email subject",
2021
body="Some text body",
2122
html=None,
23+
extra_headers={"X-MC-Tags": EmailTag.TEST},
2224
)
2325

2426
def test_send_creates_email_message_with_html_body(
@@ -28,6 +30,7 @@ def test_send_creates_email_message_with_html_body(
2830
recipients=["[email protected]"],
2931
subject="My email subject",
3032
body="Some text body",
33+
tag=EmailTag.TEST,
3134
html="<p>An HTML body</p>",
3235
)
3336

@@ -36,6 +39,7 @@ def test_send_creates_email_message_with_html_body(
3639
subject="My email subject",
3740
body="Some text body",
3841
html="<p>An HTML body</p>",
42+
extra_headers={"X-MC-Tags": EmailTag.TEST},
3943
)
4044

4145
def test_send_dispatches_email_using_request_mailer(
@@ -48,6 +52,7 @@ def test_send_dispatches_email_using_request_mailer(
4852
recipients=["[email protected]"],
4953
subject="My email subject",
5054
body="Some text body",
55+
tag=EmailTag.TEST,
5156
)
5257

5358
request_mailer.send_immediately.assert_called_once_with(message)
@@ -61,6 +66,7 @@ def test_raises_smtplib_exception(self, email_service, pyramid_mailer):
6166
recipients=["[email protected]"],
6267
subject="My email subject",
6368
body="Some text body",
69+
tag=EmailTag.TEST,
6470
)
6571

6672
@pytest.fixture

Diff for: tests/unit/h/tasks/mailer_test.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import pytest
55

6+
from h.services.email import EmailTag
67
from h.tasks import mailer
78

89

@@ -14,6 +15,7 @@ def test_send_retries_if_mailing_fails(email_service):
1415
recipients=["[email protected]"],
1516
subject="My email subject",
1617
body="Some text body",
18+
tag=EmailTag.TEST,
1719
)
1820

1921
assert mailer.send.retry.called

0 commit comments

Comments
 (0)