# app/routers/mail.py from __future__ import annotations import base64 from uuid import UUID from fastapi import APIRouter, UploadFile, File, Form, Depends, status, HTTPException from fastapi.encoders import jsonable_encoder from sqlalchemy.ext.asyncio import AsyncSession from app.db import get_session from app.schemas import SendTestMailRequest, UploadMailResponse from app.schema_utils import job_to_schema from app.task_enqueue import enqueue_job_with_single_task from app.services import create_job, get_job_with_tasks from app.job_registry import routing_key from email import policy from email.parser import BytesParser router = APIRouter(prefix="/api/v1/mail", tags=["mail"]) # TODO: vorhandene Auth-Dependency einhängen async def api_key_auth(): return True def _guess_domain_from_addresses(addresses: str | None) -> str: if not addresses: return "unknown.local" # nimmt erste Adresse, extrahiert Domain first = addresses.split(",")[0].strip() if "@" in first: return first.split("@")[-1].strip().lower() return "unknown.local" @router.post("/send", status_code=status.HTTP_202_ACCEPTED) async def send_test_mail( req: SendTestMailRequest, _=Depends(api_key_auth), session: AsyncSession = Depends(get_session), ): if not req.recipients: raise HTTPException(status_code=400, detail="At least one recipient required.") domain = req.recipients[0].split("@")[-1].lower() job = await create_job( session, job_type="MailSend", domain=domain, payload=req.model_dump(mode="json") ) job = await get_job_with_tasks(session, job.id) return job_to_schema(job) @router.post("/upload", response_model=UploadMailResponse, status_code=status.HTTP_202_ACCEPTED) async def upload_mail( mailbox_id: UUID = Form(...), eml: UploadFile = File(...), _=Depends(api_key_auth), session: AsyncSession = Depends(get_session), ): raw = await eml.read() # Domain für Job.domain aus To/From ableiten try: msg = BytesParser(policy=policy.default).parsebytes(raw) domain = _guess_domain_from_addresses(msg.get("To")) or _guess_domain_from_addresses(msg.get("From")) except Exception: domain = "unknown.local" payload = { "mailbox_id": str(mailbox_id), "raw_eml_b64": base64.b64encode(raw).decode("ascii"), } job_id, task_id = await enqueue_job_with_single_task( session, job_type="mail.store", domain=domain, payload=payload, task_name="mail.store", routing_key="mail.store", ) return UploadMailResponse(id=UUID(task_id), message_id=None)