Initial status for developed files on dagda

This commit is contained in:
mailcat
2026-07-20 20:49:36 +02:00
commit 337378a362
102 changed files with 37778 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
#!/usr/bin/env python3
"""
Upload en activeer de Sieve-mailrule op australius.nl via ManageSieve (RFC 5804).
Poort: 4190 met STARTTLS.
Gebruik: python3 upload_sieve.py
"""
import socket
import ssl
import sys
import base64
import config
from pathlib import Path
SCRIPT_NAME = "mailrules"
SCRIPT_FILE = Path(__file__).parent / "mailrules.sieve"
# Als fileinto-paden "INBOX." als prefix nodig hebben op deze server:
# Zet SIEVE_PREFIX op "INBOX." en het script past de paden automatisch aan.
# Zet op "" als de server paden zonder prefix accepteert (meest gangbaar).
SIEVE_PREFIX = ""
class ManageSieveClient:
"""Minimale ManageSieve-client (RFC 5804)."""
def __init__(self, host: str, port: int):
self._sock = None
self._host = host
self._port = port
def connect(self):
raw = socket.create_connection((self._host, self._port), timeout=15)
self._sock = raw
greeting = self._readline()
if not greeting.startswith("OK"):
raise ConnectionError(f"Onverwachte greeting: {greeting!r}")
# Lees eventuele capability-regels na de greeting
self._read_capabilities()
def starttls(self):
self._send("STARTTLS")
resp = self._readline()
if not resp.startswith("OK"):
raise ConnectionError(f"STARTTLS geweigerd: {resp!r}")
context = ssl.create_default_context()
self._sock = context.wrap_socket(self._sock, server_hostname=self._host)
# Nieuwe capabilities na TLS
self._read_capabilities()
def authenticate(self, username: str, password: str):
creds = base64.b64encode(f"\x00{username}\x00{password}".encode()).decode()
self._send(f'AUTHENTICATE "PLAIN" "{creds}"')
resp = self._readline()
if not resp.startswith("OK"):
raise PermissionError(f"Authenticatie mislukt: {resp!r}")
def put_script(self, name: str, content: str):
encoded = content.encode("utf-8")
self._send(f'PUTSCRIPT "{name}" {{{len(encoded)}+}}')
self._sock.sendall(encoded)
resp = self._readline()
if not resp.startswith("OK"):
raise RuntimeError(f"PUTSCRIPT mislukt: {resp!r}")
def set_active(self, name: str):
self._send(f'SETACTIVE "{name}"')
resp = self._readline()
if not resp.startswith("OK"):
raise RuntimeError(f"SETACTIVE mislukt: {resp!r}")
def list_scripts(self) -> list[str]:
self._send("LISTSCRIPTS")
scripts = []
while True:
line = self._readline()
if line.startswith("OK"):
break
scripts.append(line)
return scripts
def logout(self):
try:
self._send("LOGOUT")
except Exception:
pass
try:
self._sock.close()
except Exception:
pass
def _send(self, cmd: str):
self._sock.sendall((cmd + "\r\n").encode())
def _readline(self) -> str:
buf = b""
while not buf.endswith(b"\n"):
chunk = self._sock.recv(1)
if not chunk:
break
buf += chunk
return buf.decode("utf-8", errors="replace").strip()
def _read_capabilities(self):
"""Lees en negeer capability-regels tot een lege regel of einde."""
# Capabilities eindigen met een lege regel of worden gevolgd door authenticatie
# We lezen tot we iets tegenkomen dat niet op een capability lijkt
# (dit is een vereenvoudiging; volledige RFC 5804 parsing is complexer)
pass
def apply_prefix(script: str, prefix: str) -> str:
"""Voeg SIEVE_PREFIX toe aan alle fileinto-paden als dat nodig is."""
if not prefix:
return script
import re
def add_prefix(m):
path = m.group(1)
if path.startswith(prefix):
return m.group(0) # al aanwezig
return f'fileinto "{prefix}{path}"'
return re.sub(r'fileinto "([^"]+)"', add_prefix, script)
def run():
if not SCRIPT_FILE.exists():
print(f"Script niet gevonden: {SCRIPT_FILE}")
sys.exit(1)
script_content = SCRIPT_FILE.read_text(encoding="utf-8")
script_content = apply_prefix(script_content, SIEVE_PREFIX)
cfg = config.load()
print(f"Script: {SCRIPT_FILE.name} ({len(script_content)} bytes)")
print(f"Server: {cfg.sieve_host}:{cfg.sieve_port}")
print(f"Account:{cfg.username}")
print(f"Naam: {SCRIPT_NAME}\n")
client = ManageSieveClient(cfg.sieve_host, cfg.sieve_port)
print("Verbinden ...")
try:
client.connect()
print(" STARTTLS ...")
client.starttls()
print(" Authenticeren ...")
client.authenticate(cfg.username, cfg.password)
except Exception as e:
print(f"Verbinding mislukt: {e}")
sys.exit(1)
# Toon bestaande scripts
scripts = client.list_scripts()
if scripts:
print(f"\nBestaande scripts op server:")
for s in scripts:
print(f" {s}")
else:
print("\nGeen bestaande scripts.")
# Bevestiging vragen
print(f"\nScript '{SCRIPT_NAME}' wordt geüpload en geactiveerd.")
bevestig = input("Typ JA om door te gaan: ").strip()
if bevestig != "JA":
print("Afgebroken.")
client.logout()
sys.exit(0)
print("\nUploaden ...")
try:
client.put_script(SCRIPT_NAME, script_content)
print(f"{SCRIPT_NAME} geüpload")
client.set_active(SCRIPT_NAME)
print(f"{SCRIPT_NAME} geactiveerd")
except Exception as e:
print(f" ✗ Mislukt: {e}")
client.logout()
sys.exit(1)
client.logout()
print("\nKlaar. Nieuwe inkomende mail wordt nu automatisch gesorteerd.")
print(f"\nAls mail niet aankomt in de verwachte mappen:")
print(f" 1. Controleer of alle mappen bestaan (maak_mappen.py)")
print(f" 2. Probeer SIEVE_PREFIX = \"INBOX.\" in dit script")
print(f" 3. Controleer server-logs via webhosting-paneel")
if __name__ == "__main__":
run()