influx-smtp-gateway/main.py

123 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
SMTP webhook server
"""
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(stream=sys.stdout,
format='%(name)s - %(levelname)s - %(message)s')
class SMTPWebhookApp:
"""
SMTP webhook server
"""
def _send_mail(self):
if not cherrypy.request.headers.get('Content-Length'):
logging.error("error: Invalid content length.")
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("error: body field is required.")
return {"status": 400, "message": "subject field is required."}
if not req_body.get('body') or req_body.get('body') == '':
logging.error("error: body field is required.")
return {"status": 400, "message": "body field is required."}
if not req_body.get('to_mail') or req_body.get('to_mail') == '':
logging.error("error: to_mail field is required.")
return {"status": 400, "message": "to_mail field is required."}
subject = req_body['subject']
body = req_body['body']
to_mail = req_body['to_mail']
try:
client = smtplib.SMTP(host=SMTP_SERVER_HOST, port=SMTP_SERVER_PORT)
except (smtplib.SMTPConnectionError, TimeoutError) 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 response
@cherrypy.expose
def send_mail(self):
"""
api endpoint for 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:
SMTP_SERVER_HOST = os.environ["SMTP_SERVER_HOST"]
FROM_MAIL = os.environ["FROM_MAIL"]
FROM_MAIL_PASSWORD = os.environ["FROM_MAIL_PASSWORD"]
except KeyError:
raise KeyError("Please check missing environment variables: "
"SMTP_SERVER_HOST, FROM_MAIL, "
"FROM_MAIL_PASSWORD")
cherrypy.server.socket_host = CHERRYPY_SERVER_HOST
cherrypy.server.socket_port = CHERRYPY_SERVER_PORT
ENGINE = cherrypy.engine
cherrypy.tree.mount(ROOT, config={})
if hasattr(ENGINE, "signal_handler"):
ENGINE.signal_handler.subscribe()
if hasattr(ENGINE, "console_control_handler"):
ENGINE.console_control_handler.subscribe()
try:
ENGINE.start()
except Exception: # pylint: disable=broad-except
sys.exit(1)
else:
ENGINE.block()