Skip to content

Commit 4dc57a6

Browse files
committed
Add reply_to parameter to Message (#115)
Support reply_to in the same way as cc/bcc: as a constructor parameter, a property, and a setter. Accepts a single address, a (name, email) tuple, or a list of addresses. The Reply-To header is rendered in the built message alongside To and Cc. Closes #115
1 parent 0628c3c commit 4dc57a6

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

emails/message.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def __init__(self,
4949
attachments: list[dict[str, Any] | BaseFile] | None = None,
5050
cc: _AddressList = None,
5151
bcc: _AddressList = None,
52+
reply_to: _AddressList = None,
5253
headers_encoding: str | None = None) -> None:
5354

5455
self._attachments: MemoryFileStore | None = None
@@ -61,6 +62,7 @@ def __init__(self,
6162
self.set_mail_to(mail_to)
6263
self.set_cc(cc)
6364
self.set_bcc(bcc)
65+
self.set_reply_to(reply_to)
6466
self.set_headers(headers)
6567
self.set_html(html=html)
6668
self.set_text(text=text)
@@ -104,6 +106,14 @@ def get_bcc(self) -> list[tuple[str | None, str | None]]:
104106

105107
bcc = property(get_bcc, set_bcc)
106108

109+
def set_reply_to(self, addr: _AddressList) -> None:
110+
self._reply_to = parse_name_and_email_list(addr)
111+
112+
def get_reply_to(self) -> list[tuple[str | None, str | None]]:
113+
return self._reply_to
114+
115+
reply_to = property(get_reply_to, set_reply_to)
116+
107117
def get_recipients_emails(self) -> list[str | None]:
108118
"""
109119
Returns message recipient's emails for actual sending.
@@ -272,6 +282,9 @@ def _build_root_message(self, message_cls: type | None = None,
272282
if self.cc:
273283
self.set_header(msg, 'Cc', ", ".join([self.encode_address_header(addr) for addr in self.cc]), encode=False)
274284

285+
if self.reply_to:
286+
self.set_header(msg, 'Reply-To', ", ".join([self.encode_address_header(addr) for addr in self.reply_to]), encode=False)
287+
275288
return msg
276289

277290
def _build_html_part(self) -> SafeMIMEText | None:

emails/testsuite/message/test_message.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,33 @@ def test_message_id():
195195
assert m.as_message()['Message-ID'] == 'XXX'
196196

197197

198+
def test_reply_to():
199+
200+
params = dict(html='...', mail_from='a@b.c', mail_to='to@x.z')
201+
202+
# Single address
203+
m = Message(reply_to='reply@x.z', **params)
204+
assert m.as_message()['Reply-To'] == 'reply@x.z'
205+
206+
# Tuple (name, email)
207+
m = Message(reply_to=('Марья', 'maria@example.net'), **params)
208+
assert 'maria@example.net' in m.as_message()['Reply-To']
209+
210+
# Multiple addresses
211+
m = Message(reply_to=['a@x.z', 'b@x.z'], **params)
212+
assert 'a@x.z' in m.as_message()['Reply-To']
213+
assert 'b@x.z' in m.as_message()['Reply-To']
214+
215+
# No reply-to by default
216+
m = Message(**params)
217+
assert m.as_message()['Reply-To'] is None
218+
219+
# Setter
220+
m = Message(**params)
221+
m.reply_to = 'reply@x.z'
222+
assert m.as_message()['Reply-To'] == 'reply@x.z'
223+
224+
198225
def test_several_recipients():
199226

200227
# Test multiple recipients in "To" header

0 commit comments

Comments
 (0)