|
#!/usr/bin/env python3 |
|
import time |
|
from datetime import date |
|
from smtplib import SMTP |
|
from email.message import EmailMessage |
|
from flask import Flask, Response, request |
|
from werkzeug.datastructures import Headers |
|
app = Flask(__name__) |
|
|
|
|
|
LIMIT_MIN_INTERVAL = 180 |
|
LIMIT_BURST = 5 |
|
|
|
limit_left = LIMIT_BURST |
|
limit_last = time.time() |
|
|
|
def has_token(): |
|
return limit_left > 0 or time.time() - limit_last > LIMIT_MIN_INTERVAL |
|
|
|
def response_limited(): |
|
headers = Headers() |
|
headers.add('retry-after', LIMIT_MIN_INTERVAL) |
|
return Response(status=429, headers=headers) |
|
|
|
@app.route("/ping", methods=['GET']) |
|
def ping(): |
|
return '', 204 if has_token() else response_limited() |
|
|
|
@app.route("/send", methods=['POST']) |
|
def post(): |
|
global limit_left, limit_last |
|
if not has_token(): |
|
return response_limited() |
|
if limit_left < LIMIT_BURST: |
|
new_tokens = (time.time() - limit_last) // LIMIT_MIN_INTERVAL |
|
limit_left = min(LIMIT_BURST, limit_left + new_tokens) |
|
limit_left -= 1 |
|
limit_last = time.time() |
|
|
|
name = request.form.get('name') or 'anonymous' |
|
email = request.form.get('email') or 'no-reply@sorz.org' |
|
message = request.form['message'] |
|
send_message(name, email, message) |
|
return 'sent', 201 |
|
|
|
def send_message(name, reply, content): |
|
msg = EmailMessage() |
|
msg.set_content(content) |
|
msg['Subject'] = f'Message on example.com ({date.today()})' |
|
msg['From'] = f'{name} <comments@example.com>' |
|
msg['To'] = 'you@example.com' |
|
msg['Reply-To'] = f"{name} <{reply}>" |
|
with SMTP('localhost') as smtp: |
|
smtp.send_message(msg) |
|
|
|
if __name__ == "__main__": |
|
app.run('127.0.0.80', 8000) |