from pathlib import Path from typing import List from reportlab.lib import colors from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib.units import cm from reportlab.platypus import ( PageBreak, Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle, ) from models import Account def _section(title: str, rows, col_widths=(5 * cm, 11 * cm)): styles = getSampleStyleSheet() elements = [Paragraph(title, styles["Heading2"])] data = [[k, v] for k, v in rows] t = Table(data, colWidths=list(col_widths)) t.setStyle(TableStyle([ ("BOX", (0, 0), (-1, -1), 0.5, colors.grey), ("INNERGRID", (0, 0), (-1, -1), 0.25, colors.lightgrey), ("BACKGROUND", (0, 0), (0, -1), colors.whitesmoke), ("VALIGN", (0, 0), (-1, -1), "TOP"), ("FONT", (0, 0), (-1, -1), "Helvetica", 10), ("LEFTPADDING", (0, 0), (-1, -1), 4), ("RIGHTPADDING", (0, 0), (-1, -1), 4), ])) elements.append(t) elements.append(Spacer(1, 0.4 * cm)) return elements def _build_user_section(account: Account, smtp_port: int, pop_port: int, pop_ssl: bool): styles = getSampleStyleSheet() elements = [ Paragraph(f"Zugangsdaten – {account.vollname}", styles["Title"]), Spacer(1, 0.3 * cm), Paragraph(f"Hauptemail: {account.emailadresse}", styles["Normal"]), Spacer(1, 0.4 * cm), ] elements += _section("Plesk Mailpostfach (Backend, eingehend für POP3-Sammler)", [ ("Mailserver", account.pleskhost), ("Benutzername", account.emailadresse), ("Passwort", account.pleskemailkennwort), ("Hinweis", "Anmeldung nur am Mailserver – keine Plesk-Webinterface-Anmeldung."), ]) pop_proto = "SSL" if pop_ssl else "unverschlüsselt" elements += _section("Kerio Connect (Hauptmailkonto)", [ ("Webmail", f"https://{account.keriohost}/webmail/"), ("Benutzername", account.emailadresse), ("Passwort", account.kerioemailkennwort), ("SMTP-Server (Versand)", f"{account.keriohost}:{smtp_port} (SSL)"), ("IMAP/POP-Server", f"{account.keriohost}"), ("POP3-Sammler", f"holt automatisch von {account.pleskhost}:{pop_port} ({pop_proto}), " f"behält 14 Tage auf dem Server"), ]) quota = f"{account.nextcloudspeicher} GB" if account.nextcloudspeicher else "unlimitiert" elements += _section("Nextcloud", [ ("URL", f"https://{account.nextcloudhost}"), ("Benutzername", account.nextcloud_username), ("Passwort", account.nextcloudkennwort), ("Email (hinterlegt)", account.emailadresse), ("Gruppe", account.nextcloudgruppe or "–"), ("Speicher", quota), ]) return elements def write_user_pdf(path: Path, account: Account, smtp_port: int, pop_port: int, pop_ssl: bool) -> None: doc = SimpleDocTemplate( str(path), pagesize=A4, leftMargin=2 * cm, rightMargin=2 * cm, topMargin=2 * cm, bottomMargin=2 * cm, title=f"Zugangsdaten {account.vollname}", ) doc.build(_build_user_section(account, smtp_port, pop_port, pop_ssl)) def write_combined_pdf(path: Path, accounts: List[Account], smtp_port: int, pop_port: int, pop_ssl: bool) -> None: doc = SimpleDocTemplate( str(path), pagesize=A4, leftMargin=2 * cm, rightMargin=2 * cm, topMargin=2 * cm, bottomMargin=2 * cm, title="Zugangsdaten (Sammel-PDF)", ) flow = [] for i, acc in enumerate(accounts): flow += _build_user_section(acc, smtp_port, pop_port, pop_ssl) if i < len(accounts) - 1: flow.append(PageBreak()) doc.build(flow) # ---------- Minimal-PDF (nur Email + Cloud, ohne Plesk/POP3-Sammler) ---------- def _build_minimal_section(account: Account, smtp_port: int, imap_port: int): styles = getSampleStyleSheet() elements = [ Paragraph(f"Zugangsdaten – {account.vollname}", styles["Title"]), Spacer(1, 0.4 * cm), ] elements += _section("Email", [ ("Emailadresse", account.emailadresse), ("Kennwort", account.kerioemailkennwort), ("SMTP-Server", f"{account.keriohost}:{smtp_port} (SSL)"), ("IMAP-Server", f"{account.keriohost}:{imap_port} (SSL)"), ]) elements += _section("Cloud", [ ("Cloud URL", f"https://{account.nextcloudhost}"), ("Benutzername", account.nextcloud_username), ("Kennwort", account.nextcloudkennwort), ]) return elements def write_user_minimal_pdf(path: Path, account: Account, smtp_port: int, imap_port: int) -> None: doc = SimpleDocTemplate( str(path), pagesize=A4, leftMargin=2 * cm, rightMargin=2 * cm, topMargin=2 * cm, bottomMargin=2 * cm, title=f"Zugangsdaten {account.vollname}", ) doc.build(_build_minimal_section(account, smtp_port, imap_port)) def write_combined_minimal_pdf(path: Path, accounts: List[Account], smtp_port: int, imap_port: int) -> None: doc = SimpleDocTemplate( str(path), pagesize=A4, leftMargin=2 * cm, rightMargin=2 * cm, topMargin=2 * cm, bottomMargin=2 * cm, title="Zugangsdaten minimal (Sammel-PDF)", ) flow = [] for i, acc in enumerate(accounts): flow += _build_minimal_section(acc, smtp_port, imap_port) if i < len(accounts) - 1: flow.append(PageBreak()) doc.build(flow)