inital commit

This commit is contained in:
2026-06-08 15:57:11 +02:00
parent aaf8729663
commit d9ca48addc
114 changed files with 12172 additions and 1 deletions

View File

@@ -0,0 +1,71 @@
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from app.mailer.campaign.loader import CampaignLoadError, CampaignSchemaError, load_campaign_config
from app.mailer.campaign.validation import Severity, validate_campaign_config
def _default_campaign_path() -> Path:
return Path(__file__).resolve().parents[1] / "examples" / "campaign.json"
def _print_text_report(report) -> None:
print(f"Campaign: {report.campaign_name} ({report.campaign_id})")
print(f"Entries: {report.entries_mode}" + (f", {report.entries_count} item(s)" if report.entries_count is not None else ""))
print(f"Attachments base path: {report.attachments_base_path}")
print(f"Rate limit: {report.rate_limit}")
print(f"IMAP append: {'enabled' if report.imap_append_enabled else 'disabled'}")
print(f"Issues: {report.error_count} error(s), {report.warning_count} warning(s)")
if report.issues:
print()
for issue in report.issues:
location = f" [{issue.path}]" if issue.path else ""
print(f"- {issue.severity.upper()} {issue.code}{location}: {issue.message}")
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Validate a MultiMailer campaign JSON file.")
parser.add_argument("--campaign", default=str(_default_campaign_path()), help="Path to campaign JSON file")
parser.add_argument("--schema", default=None, help="Optional path to campaign.schema.json")
parser.add_argument("--no-schema", action="store_true", help="Skip JSON Schema validation")
parser.add_argument("--check-files", action="store_true", help="Check referenced local files and CSV headers")
parser.add_argument("--json", action="store_true", help="Print machine-readable validation report")
args = parser.parse_args(argv)
campaign_path = Path(args.campaign).resolve()
try:
config = load_campaign_config(
campaign_path,
validate_schema=not args.no_schema,
schema_path=args.schema,
)
report = validate_campaign_config(config, campaign_file=campaign_path, check_files=args.check_files)
except CampaignSchemaError as exc:
if args.json:
print(json.dumps({"ok": False, "schema_errors": [error.__dict__ for error in exc.errors]}, indent=2), file=sys.stdout)
else:
print(str(exc), file=sys.stderr)
for error in exc.errors:
print(f"- {error.path}: {error.message}", file=sys.stderr)
return 2
except CampaignLoadError as exc:
print(str(exc), file=sys.stderr)
return 2
except Exception as exc:
print(f"campaign validation failed: {exc}", file=sys.stderr)
return 2
if args.json:
print(report.model_dump_json(indent=2))
else:
_print_text_report(report)
return 0 if report.ok else 1
if __name__ == "__main__":
raise SystemExit(main())