Added Send mail functionality & Dockerized application #1
|
@ -13,6 +13,10 @@ RUN pip install --upgrade pip
|
||||||
COPY ./requirements.txt .
|
COPY ./requirements.txt .
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
# add user
|
||||||
|
RUN adduser --disabled-password --gecos '' service
|
||||||
|
USER service
|
||||||
|
|
||||||
# copy project
|
# copy project
|
||||||
COPY . .
|
COPY . .
|
||||||
ENTRYPOINT ["/usr/src/app/entrypoint.sh", "--user"]
|
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
|
89
main.py
89
main.py
|
@ -7,10 +7,15 @@ import os
|
||||||
import json
|
import json
|
||||||
import smtplib
|
import smtplib
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
import cherrypy
|
import cherrypy
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig(filename='app.log', filemode='w',
|
||||||
|
format='%(name)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
|
|
||||||
PeterSurda marked this conversation as resolved
|
|||||||
class SMTPWebhookApp:
|
class SMTPWebhookApp:
|
||||||
|
@ -19,51 +24,87 @@ class SMTPWebhookApp:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _send_mail(self):
|
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.ehlo()
|
||||||
client.starttls()
|
client.starttls()
|
||||||
client.ehlo()
|
client.ehlo()
|
||||||
client.login(msg["From"], FROM_MAIL_PASSWORD)
|
client.login(msg["From"], FROM_MAIL_PASSWORD)
|
||||||
client.sendmail(msg['From'], msg['To'], msg.as_string())
|
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()
|
client.quit()
|
||||||
return "mail sent successfully"
|
return response
|
||||||
except Exception as e:
|
|
||||||
return "some error: {}".format(e)
|
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def send_mail(self):
|
def send_mail(self):
|
||||||
"""
|
"""
|
||||||
api endpoint for send mail
|
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()
|
ROOT = SMTPWebhookApp()
|
||||||
|
|
||||||
|
SMTP_SERVER_PORT = 587
|
||||||
|
CHERRYPY_SERVER_HOST = "0.0.0.0"
|
||||||
|
CHERRYPY_SERVER_PORT = 8081
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
SERVER_HOST = os.environ["server_host"]
|
SMTP_SERVER_HOST = os.environ["SMTP_SERVER_HOST"]
|
||||||
SERVER_PORT = os.environ["server_port"]
|
TO_MAIL = os.environ["TO_MAIL"]
|
||||||
TO_MAIL = os.environ["to_mail"]
|
FROM_MAIL = os.environ["FROM_MAIL"]
|
||||||
FROM_MAIL = os.environ["from_mail"]
|
FROM_MAIL_PASSWORD = os.environ["FROM_MAIL_PASSWORD"]
|
||||||
FROM_MAIL_PASSWORD = os.environ["from_mail_password"]
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise KeyError("Please check missing environment variables: to_mail, "
|
raise KeyError("Please check missing environment variables: "
|
||||||
"from_mail, from_mail_password")
|
"SMTP_SERVER_HOST, TO_MAIL, FROM_MAIL, "
|
||||||
|
"FROM_MAIL_PASSWORD")
|
||||||
|
|
||||||
cherrypy.server.socket_host = "0.0.0.0"
|
cherrypy.server.socket_host = CHERRYPY_SERVER_HOST
|
||||||
cherrypy.server.socket_port = 8081
|
cherrypy.server.socket_port = CHERRYPY_SERVER_PORT
|
||||||
ENGINE = cherrypy.engine
|
ENGINE = cherrypy.engine
|
||||||
|
|
||||||
cherrypy.tree.mount(ROOT, config={})
|
cherrypy.tree.mount(ROOT, config={})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user
this should go under
__main__