added backends, improved templating, rbac
This commit is contained in:
116
server/app/api/v1/mail.py
Normal file
116
server/app/api/v1/mail.py
Normal file
@@ -0,0 +1,116 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from app.api.v1.schemas import (
|
||||
MailConnectionTestResponse,
|
||||
MailImapFolderListResponse,
|
||||
MailImapFolderResponse,
|
||||
MailImapTestRequest,
|
||||
MailSmtpTestRequest,
|
||||
)
|
||||
from app.auth.dependencies import ApiPrincipal, require_scope
|
||||
from app.mailer.sending.imap import list_imap_folders, test_imap_login
|
||||
from app.mailer.sending.smtp import test_smtp_login
|
||||
|
||||
router = APIRouter(prefix="/mail", tags=["mail"])
|
||||
|
||||
|
||||
def _safe_error_message(exc: Exception) -> str:
|
||||
text = str(exc).strip()
|
||||
return text or exc.__class__.__name__
|
||||
|
||||
|
||||
@router.post("/test-smtp", response_model=MailConnectionTestResponse)
|
||||
def test_smtp_settings(
|
||||
payload: MailSmtpTestRequest,
|
||||
principal: ApiPrincipal = Depends(require_scope("campaign:write")),
|
||||
):
|
||||
"""Test SMTP connectivity/login without sending any message."""
|
||||
|
||||
del principal
|
||||
try:
|
||||
result = test_smtp_login(smtp_config=payload)
|
||||
return MailConnectionTestResponse(
|
||||
ok=True,
|
||||
protocol="smtp",
|
||||
host=result.host,
|
||||
port=result.port,
|
||||
security=result.security,
|
||||
message="SMTP connection successful.",
|
||||
details={"authenticated": result.authenticated},
|
||||
)
|
||||
except Exception as exc:
|
||||
return MailConnectionTestResponse(
|
||||
ok=False,
|
||||
protocol="smtp",
|
||||
host=payload.host,
|
||||
port=payload.port,
|
||||
security=payload.security.value,
|
||||
message=_safe_error_message(exc),
|
||||
details={"error_type": exc.__class__.__name__},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/test-imap", response_model=MailConnectionTestResponse)
|
||||
def test_imap_settings(
|
||||
payload: MailImapTestRequest,
|
||||
principal: ApiPrincipal = Depends(require_scope("campaign:write")),
|
||||
):
|
||||
"""Test IMAP connectivity/login without selecting or appending messages."""
|
||||
|
||||
del principal
|
||||
try:
|
||||
result = test_imap_login(imap_config=payload)
|
||||
return MailConnectionTestResponse(
|
||||
ok=True,
|
||||
protocol="imap",
|
||||
host=result.host,
|
||||
port=result.port,
|
||||
security=result.security,
|
||||
message="IMAP connection successful.",
|
||||
details={"authenticated": result.authenticated},
|
||||
)
|
||||
except Exception as exc:
|
||||
return MailConnectionTestResponse(
|
||||
ok=False,
|
||||
protocol="imap",
|
||||
host=payload.host,
|
||||
port=payload.port,
|
||||
security=payload.security.value,
|
||||
message=_safe_error_message(exc),
|
||||
details={"error_type": exc.__class__.__name__},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/list-imap-folders", response_model=MailImapFolderListResponse)
|
||||
def list_imap_folder_settings(
|
||||
payload: MailImapTestRequest,
|
||||
principal: ApiPrincipal = Depends(require_scope("campaign:write")),
|
||||
):
|
||||
"""List visible IMAP folders and return the best Sent-folder guess."""
|
||||
|
||||
del principal
|
||||
try:
|
||||
result = list_imap_folders(imap_config=payload)
|
||||
folders = [MailImapFolderResponse(name=item.name, flags=item.flags) for item in result.folders]
|
||||
return MailImapFolderListResponse(
|
||||
ok=True,
|
||||
host=result.host,
|
||||
port=result.port,
|
||||
security=result.security,
|
||||
message=f"Found {len(folders)} IMAP folder(s).",
|
||||
folders=folders,
|
||||
detected_sent_folder=result.detected_sent_folder,
|
||||
)
|
||||
except Exception as exc:
|
||||
return MailImapFolderListResponse(
|
||||
ok=False,
|
||||
host=payload.host,
|
||||
port=payload.port,
|
||||
security=payload.security.value,
|
||||
message=_safe_error_message(exc),
|
||||
folders=[],
|
||||
detected_sent_folder=None,
|
||||
details={"error_type": exc.__class__.__name__},
|
||||
)
|
||||
Reference in New Issue
Block a user