Skip to content

Commit

Permalink
Add SSL and authentication support in EmailAlert
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnysharmagts committed Apr 15, 2019
1 parent be60e1b commit 01eb666
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 11 deletions.
58 changes: 48 additions & 10 deletions cloudmarker/alerts/emailalert.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@
class EmailAlert:
"""A plugin to send email notification for anomalies found."""

def __init__(self, host, port, subject, to, sender, body):
def __init__(self, host, port, subject, to, sender, body,
use_ssl, username=None, password=None):
"""Create an instance of :class:`EmailAlert` plugin.
Arguments:
host (string): Server hostname for SMTP.
host (str): Server hostname for SMTP.
port (int): Server port for SMTP.
subject (string): Subject line for email.
to (list): List of recipients (string).
sender (string): From field for email.
body (string): Email body.
subject (str): Subject line for email.
to (list): List of recipients (str).
sender (str): From field for email.
body (str): Email body.
use_ssl (bool): Is SSL Connection required
username (str): username of email account
password (str): password of email account
"""
self.host = host
self.port = port
Expand All @@ -33,6 +36,9 @@ def __init__(self, host, port, subject, to, sender, body):
self.sender = sender
self.body = body
self.stringbuffer = []
self.use_ssl = use_ssl
self.username = username
self.password = password

def write(self, record):
"""Write JSON records to the file system.
Expand All @@ -56,6 +62,11 @@ def done(self):
this example implementation, we properly terminate the JSON
array in the email body.
The connection is made based whether the SMTP or SMTP_SSL is
required which is determined by ``use_ssl`` param.
In case if no authentication is required then ``use_ssl``
can be ``False`` else ``True``.
"""
message = MIMEMultipart()
message['Date'] = email.utils.formatdate(localtime=True)
Expand All @@ -68,10 +79,37 @@ def done(self):
self.body = ''.join(self.stringbuffer)
message.attach(MIMEText(self.body))

smtp_connection = smtplib.SMTP(host=self.host, port=self.port)
smtp = self._prepare_smtp_session()
try:
smtp_connection.sendmail(self.sender, self.to, message.as_string())
smtp.sendmail(self.sender, self.to, message.as_string())
except smtplib.SMTPException as e:
_log.error('Failed to send email: %s', e)
finally:
smtp_connection.quit()
smtp.quit()

def _prepare_smtp_session(self):
"""Return SMTP connection object.
Create a SMTP connection based on whether the SSL param.
If SSL connection is required (for eg: in case of gmail) then
method will return a SMTP_SSL connection. In other cases if the
authentication is not required or SMTP_SSL connection is not
required then a plain SMTP connection object is returned.
# For gmail follow the steps given below even to work for 2 factor
authentication
# 1. Log-in into Gmail with your account
# 2. Navigate to https://security.google.com/settings/security/
apppasswords
# 3. In 'select app' choose 'custom', give it an arbitrary name and
press generate
# 4. It will give you 16 chars token.
# 5. Use that token as password for login
# 6. Host is smtp.gmail.com and port is 465
"""
# In case no authentication is required then no need to login
if self.use_ssl:
smtp = smtplib.SMTP_SSL(host=self.host, port=self.port)
smtp.set_debuglevel(True)
smtp.login(self.username, self.password)
return smtp
return smtplib.SMTP(host=self.host, port=self.port)
3 changes: 3 additions & 0 deletions config.base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ alerts:
emailalert:
plugin: cloudmarker.alerts.emailalert.EmailAlert
params:
is_ssl_required: True
host: smtp.example.com
port: 25
sender: CloudMarker Alert <no-reply@example.com>
to:
- recipient@example.com
subject: Anomaly notification
body: default text
username: alice
password: alice@123

audits:
mockaudit:
Expand Down
4 changes: 3 additions & 1 deletion pylama.ini
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ ignore = R0911
# R0911 Too many return statements (8/6) [pylint]

[pylama:cloudmarker/alerts/emailalert.py]
ignore = R0913,C0412
ignore = R0913,C0412,R0902

# R0902 Too many instance attributes (10/7) [pylint]

[pylama:cloudmarker/stores/splunkhecstore.py]
ignore = R0913,W0703
Expand Down

0 comments on commit 01eb666

Please sign in to comment.