add manual/api/ssh Plesk-Backends, Minimal-PDF, --pdf-only und GUI-Verbesserungen
- PLESK_BACKEND={manual,api,ssh}: manual als Default für Shared Hosts,
api unverändert, ssh ruft `plesk bin mail` per paramiko auf.
- POP3_PORT default 995, POP3_SSL mit Auto-Erkennung anhand Port.
- Kerio: User wird mit mayChangePassword=False angelegt.
- Zusätzliche Minimal-PDF (nur Email + Cloud) pro Konto + Sammel-Variante,
IMAP-Port konfigurierbar.
- CLI-Flag --pdf-only und entsprechender GUI-Button "📄 Nur PDF".
- GUI: Lösch-Button "✕ löschen" sichtbarer, letzte Zeile löschbar.
- PDFs sind kunden-tauglich (kein Status-Block, kein ACHTUNG-Hinweis);
Anlage-Status separat in _admin_report_<ts>.txt.
- README dokumentiert die Skip-Logik pro Dienst und ihre Caveats.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,10 @@ from typing import Callable, List, Tuple
|
||||
|
||||
from config import Config
|
||||
from models import Account, AccountResult, StepResult
|
||||
from pdf import write_combined_pdf, write_user_pdf
|
||||
from pdf import (
|
||||
write_combined_minimal_pdf, write_combined_pdf,
|
||||
write_user_minimal_pdf, write_user_pdf,
|
||||
)
|
||||
|
||||
|
||||
def _detect_delimiter(path: Path) -> str:
|
||||
@@ -141,7 +144,7 @@ def _deploy_one(account: Account, cfg: Config, log: Callable[[str], None]) -> Ac
|
||||
server=account.pleskhost,
|
||||
login_name=account.emailadresse,
|
||||
password=account.pleskemailkennwort,
|
||||
port=cfg.POP3_PORT, ssl=True,
|
||||
port=cfg.POP3_PORT, ssl=cfg.POP3_SSL,
|
||||
leave_days=cfg.POP3_KEEP_DAYS,
|
||||
)
|
||||
result.steps.append(StepResult("Kerio", "angelegt", "inkl. POP3-Sammler"))
|
||||
@@ -212,6 +215,34 @@ def _write_admin_report(path: Path, results: List[AccountResult],
|
||||
path.write_text("\n".join(lines), encoding="utf-8")
|
||||
|
||||
|
||||
def pdf_only(accounts: List[Account], cfg: Config,
|
||||
output_dir, log: Callable[[str], None] = print) -> Path:
|
||||
"""Nur PDFs schreiben – KEIN Plesk/Kerio/Nextcloud-Aufruf.
|
||||
|
||||
Praktisch wenn die Konten schon angelegt sind oder die CSV nochmal
|
||||
durchgejagt werden soll, um die PDFs neu zu generieren.
|
||||
"""
|
||||
output_dir = Path(output_dir)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
for i, acc in enumerate(accounts, 1):
|
||||
log(f"[{i}/{len(accounts)}] {acc.vollname} <{acc.emailadresse}>")
|
||||
safe = "".join(c if c.isalnum() or c in "-_." else "_" for c in acc.emailadresse)
|
||||
per_pdf = output_dir / f"zugangsdaten_{safe}.pdf"
|
||||
per_min = output_dir / f"zugangsdaten_minimal_{safe}.pdf"
|
||||
write_user_pdf(per_pdf, acc, cfg.SMTP_PORT, cfg.POP3_PORT, cfg.POP3_SSL)
|
||||
write_user_minimal_pdf(per_min, acc, cfg.SMTP_PORT, cfg.IMAP_PORT)
|
||||
log(f" ⤷ PDF: {per_pdf}")
|
||||
log(f" ⤷ PDF (minimal): {per_min}")
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
combined = output_dir / f"zugangsdaten_gesamt_{timestamp}.pdf"
|
||||
combined_min = output_dir / f"zugangsdaten_gesamt_minimal_{timestamp}.pdf"
|
||||
write_combined_pdf(combined, accounts, cfg.SMTP_PORT, cfg.POP3_PORT, cfg.POP3_SSL)
|
||||
write_combined_minimal_pdf(combined_min, accounts, cfg.SMTP_PORT, cfg.IMAP_PORT)
|
||||
log(f"✓ Gesamt-PDF: {combined}")
|
||||
log(f"✓ Gesamt-PDF (minimal): {combined_min}")
|
||||
return combined
|
||||
|
||||
|
||||
def run_deploy(accounts: List[Account], cfg: Config,
|
||||
output_dir, log: Callable[[str], None] = print
|
||||
) -> Tuple[List[AccountResult], Path]:
|
||||
@@ -224,13 +255,19 @@ def run_deploy(accounts: List[Account], cfg: Config,
|
||||
results.append(result)
|
||||
safe = "".join(c if c.isalnum() or c in "-_." else "_" for c in acc.emailadresse)
|
||||
per_pdf = output_dir / f"zugangsdaten_{safe}.pdf"
|
||||
write_user_pdf(per_pdf, acc, cfg.SMTP_PORT, cfg.POP3_PORT)
|
||||
per_min = output_dir / f"zugangsdaten_minimal_{safe}.pdf"
|
||||
write_user_pdf(per_pdf, acc, cfg.SMTP_PORT, cfg.POP3_PORT, cfg.POP3_SSL)
|
||||
write_user_minimal_pdf(per_min, acc, cfg.SMTP_PORT, cfg.IMAP_PORT)
|
||||
log(f" ⤷ PDF: {per_pdf}")
|
||||
log(f" ⤷ PDF (minimal): {per_min}")
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
combined = output_dir / f"zugangsdaten_gesamt_{timestamp}.pdf"
|
||||
write_combined_pdf(combined, accounts, cfg.SMTP_PORT, cfg.POP3_PORT)
|
||||
combined_min = output_dir / f"zugangsdaten_gesamt_minimal_{timestamp}.pdf"
|
||||
write_combined_pdf(combined, accounts, cfg.SMTP_PORT, cfg.POP3_PORT, cfg.POP3_SSL)
|
||||
write_combined_minimal_pdf(combined_min, accounts, cfg.SMTP_PORT, cfg.IMAP_PORT)
|
||||
log(f"✓ Gesamt-PDF: {combined}")
|
||||
log(f"✓ Gesamt-PDF (minimal): {combined_min}")
|
||||
|
||||
report = output_dir / f"_admin_report_{timestamp}.txt"
|
||||
_write_admin_report(report, results, cfg, timestamp)
|
||||
@@ -245,6 +282,8 @@ def main():
|
||||
p.add_argument("--csv", help="Pfad zur CSV-Datei (CLI-Modus)")
|
||||
p.add_argument("--output", default="./output", help="Verzeichnis für PDFs (default ./output)")
|
||||
p.add_argument("--gui", action="store_true", help="GUI starten")
|
||||
p.add_argument("--pdf-only", action="store_true",
|
||||
help="Nur PDFs aus der CSV erzeugen, keine Anlage in Plesk/Kerio/Nextcloud")
|
||||
args = p.parse_args()
|
||||
|
||||
if args.gui or not args.csv:
|
||||
@@ -259,6 +298,12 @@ def main():
|
||||
print(f"CSV-Fehler: {e}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
print(f"{len(accounts)} Account(s) eingelesen.\n")
|
||||
|
||||
if args.pdf_only:
|
||||
combined = pdf_only(accounts, cfg, args.output)
|
||||
print(f"\nFertig (nur PDF). Gesamt-PDF: {combined}")
|
||||
sys.exit(0)
|
||||
|
||||
results, combined = run_deploy(accounts, cfg, args.output)
|
||||
failed = sum(1 for r in results if r.has_errors)
|
||||
print(f"\nFertig. {len(results) - failed}/{len(results)} ohne Fehler. Gesamt-PDF: {combined}")
|
||||
|
||||
Reference in New Issue
Block a user