From e7fe463b820efb72703ddb04960d4773f02031ad Mon Sep 17 00:00:00 2001 From: "kuldeep.k@cisinlabs.com" Date: Fri, 11 Feb 2022 22:44:20 +0530 Subject: [PATCH] Updated dockerfile and Added error handling & logging --- Dockerfile | 6 +++- main.py | 89 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/Dockerfile b/Dockerfile index 43bbec8..2c6d462 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,10 @@ RUN pip install --upgrade pip COPY ./requirements.txt . RUN pip install -r requirements.txt +# add user +RUN adduser --disabled-password --gecos '' service +USER service + # copy project COPY . . -ENTRYPOINT ["/usr/src/app/entrypoint.sh", "--user"] \ No newline at end of file +ENTRYPOINT ["/usr/src/app/entrypoint.sh"] \ No newline at end of file diff --git a/main.py b/main.py index 1fe6c87..9707add 100644 --- a/main.py +++ b/main.py @@ -7,10 +7,15 @@ import os import json import smtplib import sys +import time from email.header import Header from email.mime.text import MIMEText import cherrypy +import logging + +logging.basicConfig(filename='app.log', filemode='w', + format='%(name)s - %(levelname)s - %(message)s') class SMTPWebhookApp: @@ -19,51 +24,87 @@ class SMTPWebhookApp: """ def _send_mail(self): - try: - cl = cherrypy.request.headers['Content-Length'] - rawbody = cherrypy.request.body.read(int(cl)) - req_body = json.loads(rawbody) - subject = req_body['subject'] - body = req_body['body'] - client = smtplib.SMTP(host=SERVER_HOST, port=SERVER_PORT) - msg = MIMEText(body, 'plain', 'utf-8') - msg['Subject'] = Header(subject, 'utf-8') - msg['From'] = FROM_MAIL - msg['To'] = TO_MAIL + if not cherrypy.request.headers.get('Content-Length'): + logging.error("To: {}, error: Invalid content length.".format( + TO_MAIL)) + return {"status": 400, "message": "Invalid content length."} + + cl = cherrypy.request.headers['Content-Length'] + rawbody = cherrypy.request.body.read(int(cl)) + req_body = json.loads(rawbody) + + if not req_body.get('subject') or req_body.get('subject') == '': + logging.error("To: {}, error: body field is required.".format( + TO_MAIL)) + return {"status": 400, "message": "subject field is required."} + + if not req_body.get('body') or req_body.get('body') == '': + logging.error("To: {}, error: body field is required.".format( + TO_MAIL)) + return {"status": 400, "message": "body field is required."} + + subject = req_body['subject'] + body = req_body['body'] + + try: + client = smtplib.SMTP(host=SMTP_SERVER_HOST, port=SMTP_SERVER_PORT) + except Exception as e: + time.sleep(0.2) + logging.error("To: {}, error: {}".format(TO_MAIL, e)) + return {"status": 400, "message": "SMTP client error: {}.".format( + e)} + + msg = MIMEText(body, 'plain', 'utf-8') + msg['Subject'] = Header(subject, 'utf-8') + msg['From'] = FROM_MAIL + msg['To'] = TO_MAIL + try: client.ehlo() client.starttls() client.ehlo() client.login(msg["From"], FROM_MAIL_PASSWORD) client.sendmail(msg['From'], msg['To'], msg.as_string()) + response = {"status": 200, "message": "mail sent successfully"} + logging.info("To: {}, mail sent successfully".format(TO_MAIL)) + except smtplib.SMTPException as e: + time.sleep(0.2) + logging.error("To: {}, error: {}".format(TO_MAIL, e)) + response = {"status": 500, "message": "some error: {}".format(e)} + finally: client.quit() - return "mail sent successfully" - except Exception as e: - return "some error: {}".format(e) + return response @cherrypy.expose def send_mail(self): """ api endpoint for send mail """ - return self._send_mail() + data = self._send_mail() + cherrypy.response.status = data["status"] + cherrypy.response.headers["Content-Type"] = "application/json" + return json.dumps(data["status"]).encode() ROOT = SMTPWebhookApp() +SMTP_SERVER_PORT = 587 +CHERRYPY_SERVER_HOST = "0.0.0.0" +CHERRYPY_SERVER_PORT = 8081 + if __name__ == "__main__": try: - SERVER_HOST = os.environ["server_host"] - SERVER_PORT = os.environ["server_port"] - TO_MAIL = os.environ["to_mail"] - FROM_MAIL = os.environ["from_mail"] - FROM_MAIL_PASSWORD = os.environ["from_mail_password"] + SMTP_SERVER_HOST = os.environ["SMTP_SERVER_HOST"] + TO_MAIL = os.environ["TO_MAIL"] + FROM_MAIL = os.environ["FROM_MAIL"] + FROM_MAIL_PASSWORD = os.environ["FROM_MAIL_PASSWORD"] except KeyError: - raise KeyError("Please check missing environment variables: to_mail, " - "from_mail, from_mail_password") + raise KeyError("Please check missing environment variables: " + "SMTP_SERVER_HOST, TO_MAIL, FROM_MAIL, " + "FROM_MAIL_PASSWORD") - cherrypy.server.socket_host = "0.0.0.0" - cherrypy.server.socket_port = 8081 + cherrypy.server.socket_host = CHERRYPY_SERVER_HOST + cherrypy.server.socket_port = CHERRYPY_SERVER_PORT ENGINE = cherrypy.engine cherrypy.tree.mount(ROOT, config={})