airflow-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bo...@apache.org
Subject incubator-airflow git commit: AIRFLOW-261 Add bcc and cc fields to EmailOperator
Date Fri, 22 Jul 2016 11:09:51 GMT
Repository: incubator-airflow
Updated Branches:
  refs/heads/master 189e6b887 -> 7628a8656


AIRFLOW-261 Add bcc and cc fields to EmailOperator

Closes #1670 from ajayyadava/261


Project: http://git-wip-us.apache.org/repos/asf/incubator-airflow/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-airflow/commit/7628a865
Tree: http://git-wip-us.apache.org/repos/asf/incubator-airflow/tree/7628a865
Diff: http://git-wip-us.apache.org/repos/asf/incubator-airflow/diff/7628a865

Branch: refs/heads/master
Commit: 7628a8656c37110ef9ea33c5142b52305ebe9440
Parents: 189e6b8
Author: Ajay Yadava <ajaynsit@gmail.com>
Authored: Fri Jul 22 13:08:52 2016 +0200
Committer: Bolke de Bruin <bolke@xs4all.nl>
Committed: Fri Jul 22 13:08:56 2016 +0200

----------------------------------------------------------------------
 airflow/operators/email_operator.py | 10 +++++++-
 airflow/utils/email.py              | 39 +++++++++++++++++++++++---------
 tests/core.py                       | 20 +++++++++++++++-
 3 files changed, 56 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/7628a865/airflow/operators/email_operator.py
----------------------------------------------------------------------
diff --git a/airflow/operators/email_operator.py b/airflow/operators/email_operator.py
index 91a8d05..76cc56b 100644
--- a/airflow/operators/email_operator.py
+++ b/airflow/operators/email_operator.py
@@ -30,6 +30,10 @@ class EmailOperator(BaseOperator):
     :type html_content: string
     :param files: file names to attach in email
     :type files: list
+    :param cc: list of recipients to be added in CC field
+    :type cc: list or string (comma or semicolon delimited)
+    :param bcc: list of recipients to be added in BCC field
+    :type bcc: list or string (comma or semicolon delimited)
     """
 
     template_fields = ('subject', 'html_content')
@@ -43,12 +47,16 @@ class EmailOperator(BaseOperator):
             subject,
             html_content,
             files=None,
+            cc=None,
+            bcc=None,
             *args, **kwargs):
         super(EmailOperator, self).__init__(*args, **kwargs)
         self.to = to
         self.subject = subject
         self.html_content = html_content
         self.files = files or []
+        self.cc = cc
+        self.bcc = bcc
 
     def execute(self, context):
-        send_email(self.to, self.subject, self.html_content, files=self.files)
+        send_email(self.to, self.subject, self.html_content, files=self.files, cc=self.cc,
bcc=self.bcc)

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/7628a865/airflow/utils/email.py
----------------------------------------------------------------------
diff --git a/airflow/utils/email.py b/airflow/utils/email.py
index c19bb89..6fe8662 100644
--- a/airflow/utils/email.py
+++ b/airflow/utils/email.py
@@ -33,17 +33,17 @@ from email.utils import formatdate
 from airflow import configuration
 
 
-def send_email(to, subject, html_content, files=None, dryrun=False):
+def send_email(to, subject, html_content, files=None, dryrun=False, cc=None, bcc=None):
     """
     Send email using backend specified in EMAIL_BACKEND.
     """
     path, attr = configuration.get('email', 'EMAIL_BACKEND').rsplit('.', 1)
     module = importlib.import_module(path)
     backend = getattr(module, attr)
-    return backend(to, subject, html_content, files=files, dryrun=dryrun)
+    return backend(to, subject, html_content, files=files, dryrun=dryrun, cc=cc, bcc=bcc)
 
 
-def send_email_smtp(to, subject, html_content, files=None, dryrun=False):
+def send_email_smtp(to, subject, html_content, files=None, dryrun=False, cc=None, bcc=None):
     """
     Send an email with html content
 
@@ -51,18 +51,23 @@ def send_email_smtp(to, subject, html_content, files=None, dryrun=False):
     """
     SMTP_MAIL_FROM = configuration.get('smtp', 'SMTP_MAIL_FROM')
 
-    if isinstance(to, basestring):
-        if ',' in to:
-            to = to.split(',')
-        elif ';' in to:
-            to = to.split(';')
-        else:
-            to = [to]
+    to = get_email_address_list(to)
 
     msg = MIMEMultipart('alternative')
     msg['Subject'] = subject
     msg['From'] = SMTP_MAIL_FROM
     msg['To'] = ", ".join(to)
+    recipients = to
+    if cc:
+        cc = get_email_address_list(cc)
+        msg['CC'] = ", ".join(cc)
+        recipients = recipients + cc
+
+    if bcc:
+        # don't add bcc in header
+        bcc = get_email_address_list(bcc)
+        recipients = recipients + bcc
+
     msg['Date'] = formatdate(localtime=True)
     mime_text = MIMEText(html_content, 'html')
     msg.attach(mime_text)
@@ -76,7 +81,7 @@ def send_email_smtp(to, subject, html_content, files=None, dryrun=False):
                 Name=basename
             ))
 
-    send_MIME_email(SMTP_MAIL_FROM, to, msg, dryrun)
+    send_MIME_email(SMTP_MAIL_FROM, recipients, msg, dryrun)
 
 
 def send_MIME_email(e_from, e_to, mime_msg, dryrun=False):
@@ -96,3 +101,15 @@ def send_MIME_email(e_from, e_to, mime_msg, dryrun=False):
         logging.info("Sent an alert email to " + str(e_to))
         s.sendmail(e_from, e_to, mime_msg.as_string())
         s.quit()
+
+
+def get_email_address_list(address_string):
+    if isinstance(address_string, basestring):
+        if ',' in address_string:
+            address_string = address_string.split(',')
+        elif ';' in address_string:
+            address_string = address_string.split(';')
+        else:
+            address_string = [address_string]
+
+    return address_string

http://git-wip-us.apache.org/repos/asf/incubator-airflow/blob/7628a865/tests/core.py
----------------------------------------------------------------------
diff --git a/tests/core.py b/tests/core.py
index 4f3197d..36b484b 100644
--- a/tests/core.py
+++ b/tests/core.py
@@ -1481,7 +1481,7 @@ class EmailTest(unittest.TestCase):
     def test_custom_backend(self, mock_send_email):
         configuration.set('email', 'EMAIL_BACKEND', 'tests.core.send_email_test')
         utils.email.send_email('to', 'subject', 'content')
-        send_email_test.assert_called_with('to', 'subject', 'content', files=None, dryrun=False)
+        send_email_test.assert_called_with('to', 'subject', 'content', files=None, dryrun=False,
cc=None, bcc=None)
         assert not mock_send_email.called
 
 
@@ -1506,6 +1506,24 @@ class EmailSmtpTest(unittest.TestCase):
         mimeapp = MIMEApplication('attachment')
         assert msg.get_payload()[-1].get_payload() == mimeapp.get_payload()
 
+    @mock.patch('airflow.utils.email.send_MIME_email')
+    def test_send_bcc_smtp(self, mock_send_mime):
+        attachment = tempfile.NamedTemporaryFile()
+        attachment.write(b'attachment')
+        attachment.seek(0)
+        utils.email.send_email_smtp('to', 'subject', 'content', files=[attachment.name],
cc='cc', bcc='bcc')
+        assert mock_send_mime.called
+        call_args = mock_send_mime.call_args[0]
+        assert call_args[0] == configuration.get('smtp', 'SMTP_MAIL_FROM')
+        assert call_args[1] == ['to', 'cc', 'bcc']
+        msg = call_args[2]
+        assert msg['Subject'] == 'subject'
+        assert msg['From'] == configuration.get('smtp', 'SMTP_MAIL_FROM')
+        assert len(msg.get_payload()) == 2
+        mimeapp = MIMEApplication('attachment')
+        assert msg.get_payload()[-1].get_payload() == mimeapp.get_payload()
+
+
     @mock.patch('smtplib.SMTP_SSL')
     @mock.patch('smtplib.SMTP')
     def test_send_mime(self, mock_smtp, mock_smtp_ssl):


Mime
View raw message