#!/usr/bin/env python3
# smtp-relay.py — Relais SMTP pour le formulaire de contact (mutualisé → VPS → OVH)
# Reçoit un POST HTTP du mutualisé, vérifie le token, envoie via SMTP OVH.
# Sécurité : token obligatoire + IP source restreinte (iptables/ufw).
import http.server
import json
import subprocess
import sys
import uuid
import urllib.parse

import dkim

TOKEN_FILE = "/home/alan/SITE/CRON/.smtp-relay-token"
SMTP_HOST = "ssl0.ovh.net"
SMTP_PORT = 465
SMTP_USER = "formulaire@re-info.fr"
CONFIG_FILE = "/home/alan/SITE/config/config.php"
DKIM_SELECTOR = "vps1"
DKIM_DOMAIN = "re-info.fr"
DKIM_KEY = open("/home/alan/SITE/CRON/dkim-private.pem", "rb").read()

def get_password():
    try:
        with open(CONFIG_FILE, "r", encoding="utf-8") as f:
            for line in f:
                if "SMTP_PASSWORD" in line and "getenv" in line:
                    marker = "?: '"
                    idx = line.find(marker)
                    if idx != -1:
                        start = idx + len(marker)
                        end = line.find("'", start)
                        if end != -1:
                            return line[start:end]
    except Exception:
        pass
    return ""

def get_token():
    try:
        with open(TOKEN_FILE, "r", encoding="utf-8") as f:
            return f.read().strip()
    except Exception:
        return ""

class RelayHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get("Content-Length", 0))
        body = self.rfile.read(length).decode("utf-8", "replace")
        try:
            data = json.loads(body)
        except Exception:
            self.send_error(400, "JSON invalide")
            return

        token = data.get("token", "")
        if token != get_token():
            self.send_error(403, "token invalide")
            return

        to = str(data.get("to", "")).strip()
        subject = str(data.get("subject", "")).strip()
        message = str(data.get("message", "")).strip()
        if not to or not subject or not message:
            self.send_error(400, "champs manquants (to, subject, message)")
            return

        password = get_password()
        if not password:
            self.send_error(500, "mot de passe SMTP introuvable")
            return

        mail_file = "/tmp/smtp-relay-mail.txt"
        headers = (
            "From: formulaire@re-info.fr\r\n"
            "To: " + to + "\r\n"
            "Subject: " + subject + "\r\n"
            "Date: " + subprocess.run(["date", "-R"], capture_output=True, text=True).stdout.strip() + "\r\n"
            "Message-ID: <relay-" + str(uuid.uuid4()) + "@re-info.fr>\r\n"
            "Content-Type: text/plain; charset=UTF-8\r\n"
            "\r\n"
        )
        raw = (headers + message).encode("utf-8")
        if not raw.endswith(b"\r\n"):
            raw += b"\r\n"
        sig = dkim.sign(raw, DKIM_SELECTOR.encode(), DKIM_DOMAIN.encode(), DKIM_KEY)
        with open(mail_file, "wb") as f:
            f.write(sig + raw)

        cmd = [
            "curl", "-s", "--url", "smtps://" + SMTP_HOST + ":" + str(SMTP_PORT),
            "--mail-from", SMTP_USER,
            "--mail-rcpt", to,
            "--user", SMTP_USER + ":" + password,
            "-T", mail_file,
        ]
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
        if result.returncode == 0:
            self.send_response(200)
            self.end_headers()
            self.wfile.write(b'{"status":"ok"}')
        else:
            self.send_response(502)
            self.end_headers()
            self.wfile.write(json.dumps({"status": "error", "detail": result.stderr[-300:]}).encode())

    def log_message(self, fmt, *args):
        sys.stderr.write("%s - %s\n" % (self.address_string(), fmt % args))

if __name__ == "__main__":
    port = 8443
    server = http.server.ThreadingHTTPServer(("0.0.0.0", port), RelayHandler)
    server.serve_forever()
