Add reply-to to std.email
Reply to address is useful when sending email from an unmonitored email address and to give user a place to respond in order to contact us. Add Reply-to as described in section 3.6.2 of RFC5222 https://tools.ietf.org/html/rfc5322#section-3.6.2 Change-Id: Ib6b2bdc130e4f9e5170eb88760d69c3e08d2a1c7
This commit is contained in:
parent
1c1923746e
commit
2cbf543103
@ -1058,6 +1058,7 @@ Sends an email message via SMTP protocol.
|
||||
- **to_addrs** - Comma separated list of recipients. *Required*.
|
||||
- **cc_addrs** - Comma separated list of CC recipients. *Optional*.
|
||||
- **bcc_addrs** - Comma separated list of BCC recipients. *Optional*.
|
||||
- **reply_to** - Comma separated list of email address. *Optional*.
|
||||
- **subject** - Subject of the message. *Optional*.
|
||||
- **body** - Text containing message body. *Optional*.
|
||||
- **html_body** - Text containing the message in HTML format. *Optional*.
|
||||
|
@ -278,9 +278,9 @@ class MistralHTTPAction(HTTPAction):
|
||||
|
||||
|
||||
class SendEmailAction(actions.Action):
|
||||
def __init__(self, from_addr, to_addrs, smtp_server, cc_addrs=None,
|
||||
bcc_addrs=None, smtp_password=None, subject=None, body=None,
|
||||
html_body=None):
|
||||
def __init__(self, from_addr, to_addrs, smtp_server, reply_to=None,
|
||||
cc_addrs=None, bcc_addrs=None, smtp_password=None,
|
||||
subject=None, body=None, html_body=None):
|
||||
super(SendEmailAction, self).__init__()
|
||||
# TODO(dzimine): validate parameters
|
||||
|
||||
@ -288,6 +288,7 @@ class SendEmailAction(actions.Action):
|
||||
self.to = to_addrs
|
||||
self.cc = cc_addrs or []
|
||||
self.bcc = bcc_addrs or []
|
||||
self.reply_to = reply_to or []
|
||||
self.subject = subject or "<No subject>"
|
||||
self.body = body or "<No body>"
|
||||
self.html_body = html_body
|
||||
@ -300,10 +301,11 @@ class SendEmailAction(actions.Action):
|
||||
def run(self, context):
|
||||
LOG.info(
|
||||
"Sending email message "
|
||||
"[from=%s, to=%s, cc=%s, bcc=%s, subject=%s, using smtp=%s, "
|
||||
"body=%s...]",
|
||||
"[from=%s, to=%s, reply_to=%s, cc=%s, bcc=%s, subject=%s, "
|
||||
"using smtp=%s, body=%s...]",
|
||||
self.sender,
|
||||
self.to,
|
||||
self.reply_to,
|
||||
self.cc,
|
||||
self.bcc,
|
||||
self.subject,
|
||||
@ -322,6 +324,7 @@ class SendEmailAction(actions.Action):
|
||||
_charset='utf-8'))
|
||||
message['Subject'] = header.Header(self.subject, 'utf-8')
|
||||
message['From'] = self.sender
|
||||
message['Reply-To'] = header.Header(', '.join(self.reply_to))
|
||||
message['To'] = ', '.join(self.to)
|
||||
|
||||
if self.cc:
|
||||
@ -351,10 +354,11 @@ class SendEmailAction(actions.Action):
|
||||
# to return a result.
|
||||
LOG.info(
|
||||
"Sending email message "
|
||||
"[from=%s, to=%s, cc=%s, bcc=%s, subject=%s, using smtp=%s, "
|
||||
"body=%s...]",
|
||||
"[from=%s, to=%s, reply_to=%s, cc=%s, bcc=%s, subject=%s, "
|
||||
" using smtp=%s, body=%s...]",
|
||||
self.sender,
|
||||
self.to,
|
||||
self.reply_to,
|
||||
self.cc,
|
||||
self.bcc,
|
||||
self.subject,
|
||||
|
@ -54,6 +54,7 @@ class SendEmailActionTest(base.BaseTest):
|
||||
super(SendEmailActionTest, self).setUp()
|
||||
self.to_addrs = ["dz@example.com", "deg@example.com",
|
||||
"xyz@example.com"]
|
||||
self.reply_to = ['reply-to@example.com']
|
||||
self.cc_addrs = ['copy@example.com']
|
||||
self.bcc_addrs = ['hidden_copy@example.com']
|
||||
self.subject = "Multi word subject с русскими буквами"
|
||||
@ -64,6 +65,7 @@ class SendEmailActionTest(base.BaseTest):
|
||||
self.from_addr = "bot@example.com"
|
||||
|
||||
self.to_addrs_str = ", ".join(self.to_addrs)
|
||||
self.reply_to_str = ", ".join(self.reply_to)
|
||||
self.ctx = mock.Mock()
|
||||
|
||||
@testtools.skipIf(not LOCAL_SMTPD, "Setup local smtpd to run it")
|
||||
@ -84,7 +86,6 @@ class SendEmailActionTest(base.BaseTest):
|
||||
self.smtp_server = 'mail.example.com:25'
|
||||
self.from_addr = "bot@example.com"
|
||||
self.smtp_password = 'secret'
|
||||
|
||||
action = std.SendEmailAction(
|
||||
from_addr=self.from_addr,
|
||||
to_addrs=self.to_addrs,
|
||||
@ -235,6 +236,35 @@ class SendEmailActionTest(base.BaseTest):
|
||||
self.assertEqual(self.from_addr, message['from'])
|
||||
self.assertEqual(self.to_addrs_str, message['to'])
|
||||
|
||||
@mock.patch('smtplib.SMTP')
|
||||
def test_send_email_with_reply_to(self, smtp):
|
||||
action = std.SendEmailAction(
|
||||
from_addr=self.from_addr,
|
||||
to_addrs=self.to_addrs,
|
||||
reply_to=self.reply_to,
|
||||
bcc_addrs=self.bcc_addrs,
|
||||
smtp_server=self.smtp_server,
|
||||
smtp_password=None,
|
||||
subject=self.subject,
|
||||
body=self.body
|
||||
)
|
||||
|
||||
action.run(self.ctx)
|
||||
|
||||
smtp.assert_called_once_with(self.smtp_server)
|
||||
|
||||
sendmail = smtp.return_value.sendmail
|
||||
|
||||
self.assertTrue(sendmail.called, "should call sendmail")
|
||||
self.assertEqual(
|
||||
self.from_addr, sendmail.call_args[1]['from_addr'])
|
||||
|
||||
message = parser.Parser().parsestr(sendmail.call_args[1]['msg'])
|
||||
|
||||
self.assertEqual(self.from_addr, message['from'])
|
||||
self.assertEqual(self.to_addrs_str, message['to'])
|
||||
self.assertEqual(self.reply_to_str, message['reply-to'])
|
||||
|
||||
@mock.patch('smtplib.SMTP')
|
||||
def test_send_email_html(self, smtp):
|
||||
action = std.SendEmailAction(
|
||||
|
@ -31,7 +31,7 @@ class ActionManagerTest(base.DbTestCase):
|
||||
self.assertEqual(http_action_input, std_http.input)
|
||||
|
||||
std_email_input = (
|
||||
"from_addr, to_addrs, smtp_server, cc_addrs=null, "
|
||||
"from_addr, to_addrs, smtp_server, reply_to=null, cc_addrs=null, "
|
||||
"bcc_addrs=null, smtp_password=null, subject=null, body=null, "
|
||||
"html_body=null"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user