Skip to content
This repository was archived by the owner on Jun 9, 2024. It is now read-only.

Commit 2a01508

Browse files
authored
Add support for ReplyTo addresses in emails (#6)
1 parent 6ef87cf commit 2a01508

5 files changed

Lines changed: 47 additions & 7 deletions

File tree

pythonit_toolkit/emails/backends/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from abc import ABC, abstractmethod
2-
from typing import Optional
2+
from typing import Dict, List, Optional
33

44
from pythonit_toolkit.emails.templates import EmailTemplate
55

@@ -16,6 +16,7 @@ def send_email(
1616
subject: str,
1717
from_: str,
1818
to: str,
19-
variables: Optional[dict[str, str]] = None
19+
variables: Optional[Dict[str, str]] = None,
20+
reply_to: List[str] = None
2021
):
2122
pass

pythonit_toolkit/emails/backends/local.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional
1+
from typing import Dict, List, Optional
22

33
from pythonit_toolkit.emails.templates import EmailTemplate
44

@@ -16,12 +16,16 @@ def send_email(
1616
subject: str,
1717
from_: str,
1818
to: str,
19-
variables: Optional[dict[str, str]] = None,
19+
variables: Optional[Dict[str, str]] = None,
20+
reply_to: List[str] = None,
2021
):
22+
reply_to = reply_to or []
23+
2124
print("=== Email sending ===")
2225
print(f"Template: {template}")
2326
print(f"From: {from_}")
2427
print(f"To: {to}")
2528
print(f"Subject: {subject}")
2629
print(f"Variables: {str(variables)}")
30+
print(f"Reply to: {str(reply_to)}")
2731
print("=== End Email sending ===")

pythonit_toolkit/emails/backends/ses.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from typing import Optional
2+
from typing import Dict, List, Optional
33
import html
44
import boto3
55
from pythonit_toolkit.emails.templates import EmailTemplate
@@ -19,14 +19,18 @@ def send_email(
1919
subject: str,
2020
from_: str,
2121
to: str,
22-
variables: Optional[dict[str, str]] = None,
22+
variables: Optional[Dict[str, str]] = None,
23+
reply_to: List[str] = None,
2324
):
25+
reply_to = reply_to or []
26+
2427
variables = self.encode_vars({"subject": subject, **(variables or {})})
2528
self.ses.send_templated_email(
2629
Source=from_,
2730
Destination={"ToAddresses": [to]},
2831
Template=f"pythonit-{self.environment}-{template}",
2932
TemplateData=json.dumps(variables),
33+
ReplyToAddresses=reply_to,
3034
)
3135

3236
def encode_vars(self, variables: dict[str, str]) -> dict[str, str]:

tests/emails/backends/test_local.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ async def _():
1414
to="hello@world.it",
1515
subject="Hello World!",
1616
variables={"a": "b", "c": "d"},
17+
reply_to=["test@placeholder.com"],
1718
)
1819

19-
assert mock_logger.call_count == 7
20+
assert mock_logger.call_count == 8
2021
mock_logger.assert_any_call("=== Email sending ===")
2122
mock_logger.assert_any_call(f"Template: {str(EmailTemplate.RESET_PASSWORD)}")
2223
mock_logger.assert_any_call("From: from@from.it")
2324
mock_logger.assert_any_call("To: hello@world.it")
2425
mock_logger.assert_any_call("Subject: Hello World!")
2526
mock_logger.assert_any_call("Variables: {'a': 'b', 'c': 'd'}")
27+
mock_logger.assert_any_call("Reply to: ['test@placeholder.com']")
2628
mock_logger.assert_any_call("=== End Email sending ===")

tests/emails/backends/test_ses.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ async def _():
2121
Destination={"ToAddresses": ["destination@email.it"]},
2222
Template="pythonit-production-reset-password",
2323
TemplateData='{"subject": "Subject", "a": "b", "c": "d"}',
24+
ReplyToAddresses=[],
2425
)
2526

2627

@@ -39,6 +40,33 @@ async def _():
3940
Destination={"ToAddresses": ["destination@email.it"]},
4041
Template="pythonit-production-reset-password",
4142
TemplateData='{"subject": "Subject"}',
43+
ReplyToAddresses=[],
44+
)
45+
46+
47+
@test("send email with reply to")
48+
async def _():
49+
with patch("pythonit_toolkit.emails.backends.ses.boto3") as mock_boto:
50+
SESEmailBackend("production").send_email(
51+
template=EmailTemplate.RESET_PASSWORD,
52+
subject="Subject",
53+
from_="test@email.it",
54+
to="destination@email.it",
55+
reply_to=[
56+
"test1@placeholder.com",
57+
"test2@placeholder.com",
58+
]
59+
)
60+
61+
mock_boto.client.return_value.send_templated_email.assert_called_once_with(
62+
Source="test@email.it",
63+
Destination={"ToAddresses": ["destination@email.it"]},
64+
Template="pythonit-production-reset-password",
65+
TemplateData='{"subject": "Subject"}',
66+
ReplyToAddresses=[
67+
"test1@placeholder.com",
68+
"test2@placeholder.com",
69+
],
4270
)
4371

4472

@@ -60,4 +88,5 @@ async def _():
6088
Destination={"ToAddresses": ["destination@email.it"]},
6189
Template="pythonit-production-reset-password",
6290
TemplateData='{"subject": "Subject", "a": "<a href="https://google.it">link</a>"}',
91+
ReplyToAddresses=[],
6392
)

0 commit comments

Comments
 (0)