diff --git a/bin/send-dsn b/bin/send-dsn index e3cb49c2e3ec6788bc284f3439ff9f01c56c47d8..6cc6785c493fbf78dfabcad906adbaeb3883d1f6 100755 --- a/bin/send-dsn +++ b/bin/send-dsn @@ -2,21 +2,40 @@ # Tento skript se volá při doručování pošty (například pomocí "execute" v Sieve) # a předá mail webové části OSMO přes /api/email-dsn. +import os +from pathlib import Path import requests from requests.exceptions import RequestException import sys if len(sys.argv) != 2: - print('Arguments: <URL of OSMO root>/', file=sys.stderr) + print('Arguments: <URL of OSMO root>', file=sys.stderr) sys.exit(1) osmo_url = sys.argv[1] mail = sys.stdin.buffer.read() +key_path = Path.home() / '.config/osmo/dsn-api-key' try: - reply = requests.post(f'{osmo_url}api/email-dsn', data=mail, timeout=30) -except RequestException: + with key_path.open() as f: + key = f.readline().strip() + if key == "": + print(f'Cannot read key from {key_path}', file=sys.stderr) + sys.exit(1) +except OSError as e: + print(f'Cannot read {key_path}: {e}', file=sys.stderr) + sys.exit(1) + +try: + reply = requests.post( + os.path.join(osmo_url, 'api/email-dsn'), + data=mail, + headers={'Authorization': f'Bearer {key}'}, + timeout=30) +except RequestException as e: + print(f'Error sending DSN: {e}') sys.exit(1) if reply.status_code != 200: + print(f'Error sending DSN: HTTP status {reply.status_code}') sys.exit(1) diff --git a/etc/config.py.example b/etc/config.py.example index 15d6230448b43e6bd81ca60807b76eefbca6d84e..a714932b78127839cda2fd3615ccb0808caba96c 100644 --- a/etc/config.py.example +++ b/etc/config.py.example @@ -111,3 +111,7 @@ MAILING_LIST_EXCLUDE = { # Maximální počet e-mailových adres, které jsme ochotni ve webovém rozhraní zobrazit # uživatelům bez práva unrestricted_email. EMAILS_SHOW_MAX = 500 + +# Klíč k API na zpracování mailových nedoručenek. Měl by být také uložen +# v ~/.config/osmo/dsn-api-key účtu, který volá bin/send-dsn. Nesmí obsahovat mezery. +# DSN_API_KEY = "..." diff --git a/mo/web/api_dsn.py b/mo/web/api_dsn.py index 99194148f339e5526240fa03d1400914b91f0987..87bb85e061bb9a55849a1c04e23376db1f96a964 100644 --- a/mo/web/api_dsn.py +++ b/mo/web/api_dsn.py @@ -112,8 +112,21 @@ def process_dsn_reg(dsn: db.EmailDSN) -> None: dsn.reg.dsn_id = dsn.dsn_id +def authorize_email_dsn() -> bool: + dsn_api_token = getattr(config, 'DSN_API_KEY', None) + auth_header = request.headers.get('Authorization') + if dsn_api_token is None or auth_header is None: + return False + + fields = auth_header.split() + return len(fields) == 2 and fields[1] == dsn_api_token + + @app.route('/api/email-dsn', methods=('POST',)) def api_email_dsn() -> Response: + if not authorize_email_dsn(): + raise werkzeug.exceptions.Forbidden() + body = request.get_data(cache=False) try: