From a747ed293ec4449ca15271f9476903905dbbfaf5 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 17 Jan 2020 11:11:52 +0100 Subject: deploy: add notification proxy --- notification_proxy.py | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 notification_proxy.py (limited to 'notification_proxy.py') diff --git a/notification_proxy.py b/notification_proxy.py new file mode 100644 index 0000000..ae4d73e --- /dev/null +++ b/notification_proxy.py @@ -0,0 +1,89 @@ +import smtplib +import ssl +import email.utils +import hmac +from email.mime.text import MIMEText +from datetime import datetime +import functools +import json +import binascii + +from flask import Flask, request, abort + +app = Flask(__name__) +app.config.from_pyfile('config.py') + +smtp_server = "smtp.sendgrid.net" +port = 465 + +mail_routes = {} +def mail_route(name, receiver, subject): + def wrap(func): + global routes + mail_routes[name] = (receiver, subject, func) + return func + return wrap + + +def authenticate(secret): + def wrap(func): + func.last_seqnum = 0 + @functools.wraps(func) + def wrapper(*args, **kwargs): + if not request.is_json: + abort(400) + + if not 'auth' in request.json and 'payload' in request.json: + abort(400) + + if not isinstance(request.json['auth'], str): + abort(400) + their_digest = binascii.unhexlify(request.json['auth']) + + our_digest = hmac.digest(secret.encode('utf-8'), request.json['payload'].encode('utf-8'), 'sha256') + if not hmac.compare_digest(their_digest, our_digest): + abort(403) + + try: + payload = json.loads(request.json['payload']) + except: + abort(400) + + if not isinstance(payload['seq'], int) or payload['seq'] <= func.last_seqnum: + abort(400) + + func.last_seqnum = payload['seq'] + del payload['seq'] + return func(payload) + return wrapper + return wrap + +@mail_route('klingel', 'computerstuff@jaseg.de', 'It rang!') +@authenticate(app.config['SECRET_KLINGEL']) +def klingel(_): + return f'Date: {datetime.utcnow().isoformat()}' + + +@app.route('/notify/', methods=['POST']) +def notify(route_name): + try: + context = ssl.create_default_context() + smtp = smtplib.SMTP_SSL(smtp_server, port) + smtp.login('apikey', app.config['SENDGRID_APIKEY']) + + sender = f'{route_name}@{app.config["DOMAIN"]}' + + receiver, subject, func = mail_routes[route_name] + + msg = MIMEText(func() or subject) + msg['Subject'] = subject + msg['From'] = sender + msg['To'] = receiver + msg['Date'] = email.utils.formatdate() + smtp.sendmail(sender, receiver, msg.as_string()) + finally: + smtp.quit() + return 'success' + +if __name__ == '__main__': + app.run() -- cgit