Commit 9a91e868 authored by Mikhail Ivanov's avatar Mikhail Ivanov Committed by Tamika Tannis

Amundsen Notifications functionality improvements (#363)

* Amundsen Notifications functionality improvements:
 - "Request Description" link visibility fix
 - MailClient implementation example
 - API incompatibilities fixes

* Amundsen Notifications functionality improvements:
 - "Request Description" link visibility fix
 - MailClient implementation example
 - API incompatibilities fixes
parent e5044816
...@@ -24,7 +24,6 @@ def feedback() -> Response: ...@@ -24,7 +24,6 @@ def feedback() -> Response:
try: try:
mail_client = get_mail_client() mail_client = get_mail_client()
data = request.form.to_dict() data = request.form.to_dict()
text_content = '\r\n'.join('{}:\r\n{}\r\n'.format(k, v) for k, v in data.items())
html_content = ''.join('<div><strong>{}:</strong><br/>{}</div><br/>'.format(k, v) for k, v in data.items()) html_content = ''.join('<div><strong>{}:</strong><br/>{}</div><br/>'.format(k, v) for k, v in data.items())
# action logging # action logging
...@@ -51,7 +50,7 @@ def feedback() -> Response: ...@@ -51,7 +50,7 @@ def feedback() -> Response:
'form_data': data 'form_data': data
} }
response = mail_client.send_email(subject=subject, text=text_content, html=html_content, optional_data=options) response = mail_client.send_email(html=html_content, subject=subject, optional_data=options)
status_code = response.status_code status_code = response.status_code
if status_code == HTTPStatus.OK: if status_code == HTTPStatus.OK:
......
...@@ -192,13 +192,13 @@ def send_notification(*, notification_type: str, options: Dict, recipients: List ...@@ -192,13 +192,13 @@ def send_notification(*, notification_type: str, options: Dict, recipients: List
) )
response = mail_client.send_email( response = mail_client.send_email(
recipients=recipients,
sender=sender,
subject=subject,
html=html, html=html,
subject=subject,
optional_data={ optional_data={
'email_type': notification_type, 'email_type': notification_type,
}, },
recipients=recipients,
sender=sender,
) )
status_code = response.status_code status_code = response.status_code
......
...@@ -11,20 +11,18 @@ class BaseMailClient(abc.ABC): ...@@ -11,20 +11,18 @@ class BaseMailClient(abc.ABC):
@abc.abstractmethod @abc.abstractmethod
def send_email(self, def send_email(self,
sender: str,
recipients: List[str],
subject: str,
text: str,
html: str, html: str,
optional_data: Dict) -> Response: subject: str,
optional_data: Dict,
recipients: List[str],
sender: str) -> Response:
""" """
Sends an email using the following parameters Sends an email using the following parameters
:param sender: The sending address associated with the email
:param recipients: A list of receipients for the email
:param subject: The subject of the email
:param text: Plain text email content
:param html: HTML email content :param html: HTML email content
:param subject: The subject of the email
:param optional_data: A dictionary of any values needed for custom implementations :param optional_data: A dictionary of any values needed for custom implementations
:param recipients: A list of recipients for the email
:param sender: The sending address associated with the email
:return: :return:
""" """
raise NotImplementedError # pragma: no cover raise NotImplementedError # pragma: no cover
import logging
import os
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from http import HTTPStatus
from typing import Dict, List
from flask import Response, jsonify, make_response
from amundsen_application.base.base_mail_client import BaseMailClient
# based on https://stackoverflow.com/a/6270987
class MailClient(BaseMailClient):
def __init__(self, recipients: List[str]) -> None:
self.recipients = recipients
def send_email(self,
html: str,
subject: str,
optional_data: Dict = None,
recipients: List[str] = None,
sender: str = None) -> Response:
if not sender:
sender = os.environ.get('AMUNDSEN_EMAIL') or '' # set me
if not recipients:
recipients = self.recipients
sender_pass = os.environ.get('AMUNDSEN_EMAIL_PASSWORD') or '' # set me
# Create message container - the correct MIME type
# to combine text and html is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = ', '.join(recipients)
# Record the MIME type of text/html
# and attach parts to message container.
msg.attach(MIMEText(html, 'html'))
s = smtplib.SMTP('smtp.gmail.com')
try:
s.connect('smtp.gmail.com', 587)
s.ehlo()
s.starttls()
s.ehlo()
s.login(sender, sender_pass)
message = s.send_message(msg)
payload = jsonify({'msg': message})
s.quit()
return make_response(payload, HTTPStatus.OK)
except Exception as e:
err_message = 'Encountered exception: ' + str(e)
logging.exception(err_message)
payload = jsonify({'msg': err_message})
s.quit()
return make_response(payload, HTTPStatus.INTERNAL_SERVER_ERROR)
...@@ -158,7 +158,7 @@ class TableDetail extends React.Component<TableDetailProps & RouteComponentProps ...@@ -158,7 +158,7 @@ class TableDetail extends React.Component<TableDetailProps & RouteComponentProps
editable={ data.is_editable } editable={ data.is_editable }
/> />
</EditableSection> </EditableSection>
{ !data.table_description && notificationsEnabled() && <RequestDescriptionText/> } { notificationsEnabled() && <RequestDescriptionText/> }
<section className="column-layout-2"> <section className="column-layout-2">
<section className="left-panel"> <section className="left-panel">
{ {
......
...@@ -109,31 +109,6 @@ interface MailClientFeaturesConfig { ...@@ -109,31 +109,6 @@ interface MailClientFeaturesConfig {
feedbackEnabled: boolean; feedbackEnabled: boolean;
notificationsEnabled: boolean; notificationsEnabled: boolean;
} }
/**
* MailClientFeaturesConfig - Enable/disable UI features with a dependency on
* configuring a custom mail client.
*
* feedbackEnabled - Enables the feedback feature UI
* notificationsEnabled - Enables any UI related to sending notifications to users
*/
interface MailClientFeaturesConfig {
feedbackEnabled: boolean;
notificationsEnabled: boolean;
}
/**
* MailClientFeaturesConfig - Enable/disable UI features with a dependency on
* configuring a custom mail client.
*
* feedbackEnabled - Enables the feedback feature UI
* notificationsEnabled - Enables any UI related to sending notifications to users
*/
interface MailClientFeaturesConfig {
feedbackEnabled: boolean;
notificationsEnabled: boolean;
}
/** /**
* TableProfileConfig - Customize the "Table Profile" section of the "Table Details" page. * TableProfileConfig - Customize the "Table Profile" section of the "Table Details" page.
* *
......
...@@ -372,11 +372,11 @@ class NotificationUtilsTest(unittest.TestCase): ...@@ -372,11 +372,11 @@ class NotificationUtilsTest(unittest.TestCase):
sender=test_sender sender=test_sender
) )
mock_client.send_email.assert_called_with( mock_client.send_email.assert_called_with(
recipients=expected_recipients,
sender=test_sender,
subject=mock_subject,
html=mock_html, html=mock_html,
subject=mock_subject,
optional_data={'email_type': test_notification_type}, optional_data={'email_type': test_notification_type},
recipients=expected_recipients,
sender=test_sender
) )
def test_no_recipients_for_notification(self) -> None: def test_no_recipients_for_notification(self) -> None:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment