diff --git a/email_api/app.py b/email_api/app.py new file mode 100644 index 0000000..eb73f79 --- /dev/null +++ b/email_api/app.py @@ -0,0 +1,50 @@ +from flask import Flask, request, jsonify +import smtplib +import base64 +import gzip +import logging +import os + +app = Flask(__name__) +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Konfiguration +SMTP_HOST = "postfix" # MailCow Postfix-Container +SMTP_PORT = 25 # Fest auf Port 25 ohne TLS +API_TOKEN = os.environ.get('API_TOKEN', 'your-api-token') # Muss mit Lambda übereinstimmen + +@app.route('/process/', methods=['POST']) +def process_email(domain): + # Authentifizierung via Bearer-Token + auth_header = request.headers.get('Authorization') + if not auth_header or auth_header != f'Bearer {API_TOKEN}': + return jsonify({'error': 'Unauthorized'}), 401 + + data = request.get_json() + request_id = data.get('request_id') + email_content = data.get('email_content') + compressed = data.get('compressed', False) + + logger.info(f"[{request_id}] Processing email for domain: {domain}") + + try: + # Entkomprimieren, falls komprimiert + if compressed: + email_bytes = base64.b64decode(email_content) + email_content = gzip.decompress(email_bytes).decode('utf-8') + else: + email_content = base64.b64decode(email_content).decode('utf-8') + + # An Postfix lokal weiterleiten (Port 25, kein TLS) + with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp: + smtp.sendmail('lambda@andreasknuth.de', f'inbox@{domain}', email_content) + logger.info(f"[{request_id}] Email forwarded to Postfix for {domain}") + + return jsonify({'message': 'Email processed', 'request_id': request_id}), 200 + except Exception as e: + logger.error(f"[{request_id}] Error processing email: {str(e)}") + return jsonify({'error': str(e), 'request_id': request_id}), 500 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) \ No newline at end of file diff --git a/email_api/docker_compose.yml b/email_api/docker_compose.yml new file mode 100644 index 0000000..0ed532f --- /dev/null +++ b/email_api/docker_compose.yml @@ -0,0 +1,19 @@ +services: + email-api: + container_name: email-api + image: python:3.9-slim + restart: unless-stopped + ports: + - "5000:5000" + networks: + - mail_network + volumes: + - ./email_api:/app + working_dir: /app + environment: + - API_TOKEN=your-api-token # Muss mit Lambda übereinstimmen + command: > + bash -c "pip install flask smtplib && python app.py" +networks: + mail_network: + external: true \ No newline at end of file diff --git a/email_api/email_api/app.py b/email_api/email_api/app.py new file mode 100644 index 0000000..eb73f79 --- /dev/null +++ b/email_api/email_api/app.py @@ -0,0 +1,50 @@ +from flask import Flask, request, jsonify +import smtplib +import base64 +import gzip +import logging +import os + +app = Flask(__name__) +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +# Konfiguration +SMTP_HOST = "postfix" # MailCow Postfix-Container +SMTP_PORT = 25 # Fest auf Port 25 ohne TLS +API_TOKEN = os.environ.get('API_TOKEN', 'your-api-token') # Muss mit Lambda übereinstimmen + +@app.route('/process/', methods=['POST']) +def process_email(domain): + # Authentifizierung via Bearer-Token + auth_header = request.headers.get('Authorization') + if not auth_header or auth_header != f'Bearer {API_TOKEN}': + return jsonify({'error': 'Unauthorized'}), 401 + + data = request.get_json() + request_id = data.get('request_id') + email_content = data.get('email_content') + compressed = data.get('compressed', False) + + logger.info(f"[{request_id}] Processing email for domain: {domain}") + + try: + # Entkomprimieren, falls komprimiert + if compressed: + email_bytes = base64.b64decode(email_content) + email_content = gzip.decompress(email_bytes).decode('utf-8') + else: + email_content = base64.b64decode(email_content).decode('utf-8') + + # An Postfix lokal weiterleiten (Port 25, kein TLS) + with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as smtp: + smtp.sendmail('lambda@andreasknuth.de', f'inbox@{domain}', email_content) + logger.info(f"[{request_id}] Email forwarded to Postfix for {domain}") + + return jsonify({'message': 'Email processed', 'request_id': request_id}), 200 + except Exception as e: + logger.error(f"[{request_id}] Error processing email: {str(e)}") + return jsonify({'error': str(e), 'request_id': request_id}), 500 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) \ No newline at end of file diff --git a/mailcow-configs/mailcow.conf b/mailcow-configs/mailcow.conf index c832861..97f79d1 100644 --- a/mailcow-configs/mailcow.conf +++ b/mailcow-configs/mailcow.conf @@ -43,7 +43,7 @@ REDISPASS=LsamNIsi3taCxMgOva0iVfcXOV5O # For IPv4 leave it as it is: HTTP_BIND= & HTTPS_PORT= # For IPv6 see https://docs.mailcow.email/post_installation/firststeps-ip_bindings/ -HTTP_PORT=8080 +HTTP_PORT=80 HTTP_BIND=127.0.0.1 HTTPS_PORT=8443