addes folder backup attachments logging
This commit is contained in:
+111
-2
@@ -2,15 +2,17 @@ from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.database import get_db
|
||||
from app.models.db_models import Account
|
||||
from app.models.db_models import Account, ProcessedMail
|
||||
from app.schemas.schemas import (
|
||||
AccountCreate,
|
||||
AccountListResponse,
|
||||
AccountResponse,
|
||||
AccountUpdate,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.services.encryption import decrypt, encrypt
|
||||
from app.services.imap_client import async_test_connection
|
||||
from app.services.imap_client import IMAPClient, async_test_connection
|
||||
|
||||
router = APIRouter(prefix="/api/accounts", tags=["accounts"])
|
||||
|
||||
@@ -87,6 +89,26 @@ async def test_account_connection(account_id: int, db: Session = Depends(get_db)
|
||||
return {"success": success, "message": "Verbindung erfolgreich" if success else "Verbindung fehlgeschlagen"}
|
||||
|
||||
|
||||
class TestConnectionRequest(BaseModel):
|
||||
imap_host: str
|
||||
imap_port: int = 993
|
||||
use_ssl: bool = True
|
||||
username: str
|
||||
password: str
|
||||
|
||||
|
||||
@router.post("/test-connection")
|
||||
async def test_connection_direct(data: TestConnectionRequest):
|
||||
success = await async_test_connection(
|
||||
host=data.imap_host,
|
||||
port=data.imap_port,
|
||||
username=data.username,
|
||||
password=data.password,
|
||||
use_ssl=data.use_ssl,
|
||||
)
|
||||
return {"success": success, "message": "Verbindung erfolgreich" if success else "Verbindung fehlgeschlagen"}
|
||||
|
||||
|
||||
@router.post("/{account_id}/poll-now")
|
||||
async def poll_now(account_id: int, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
@@ -95,3 +117,90 @@ async def poll_now(account_id: int, db: Session = Depends(get_db)):
|
||||
from app.services.scheduler import poll_account
|
||||
await poll_account(account_id)
|
||||
return {"message": f"Polling für '{account.name}' durchgeführt"}
|
||||
|
||||
|
||||
@router.get("/{account_id}/processed")
|
||||
def get_processed_stats(account_id: int, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
total = db.query(ProcessedMail).filter(ProcessedMail.account_id == account_id).count()
|
||||
return {"account_id": account_id, "processed_count": total}
|
||||
|
||||
|
||||
@router.delete("/{account_id}/processed")
|
||||
def reset_processed(account_id: int, folder: str | None = None, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
query = db.query(ProcessedMail).filter(ProcessedMail.account_id == account_id)
|
||||
if folder:
|
||||
query = query.filter(ProcessedMail.folder == folder)
|
||||
count = query.delete()
|
||||
db.commit()
|
||||
scope = f"Ordner '{folder}'" if folder else "alle Ordner"
|
||||
return {"message": f"Verarbeitung zurückgesetzt für {scope} ({count} Einträge)", "deleted": count}
|
||||
|
||||
|
||||
def _get_imap_client(account: Account) -> IMAPClient:
|
||||
return IMAPClient(
|
||||
host=account.imap_host,
|
||||
port=account.imap_port,
|
||||
username=account.username,
|
||||
password=decrypt(account.password),
|
||||
use_ssl=account.use_ssl,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{account_id}/folders")
|
||||
async def list_folders(account_id: int, debug: bool = False, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
|
||||
import asyncio
|
||||
def _list():
|
||||
client = _get_imap_client(account)
|
||||
with client:
|
||||
folders = client.list_folders()
|
||||
raw = None
|
||||
if debug:
|
||||
status, data = client.conn.list()
|
||||
raw = [item.decode("utf-8", errors="replace") if isinstance(item, bytes) else str(item) for item in (data or [])]
|
||||
return folders, raw
|
||||
|
||||
try:
|
||||
folders, raw = await asyncio.to_thread(_list)
|
||||
result = {"folders": folders}
|
||||
if debug and raw is not None:
|
||||
result["raw"] = raw
|
||||
return result
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"Fehler beim Abrufen der Ordner: {e}")
|
||||
|
||||
|
||||
class CreateFolderRequest(BaseModel):
|
||||
folder_name: str
|
||||
|
||||
|
||||
@router.post("/{account_id}/folders")
|
||||
async def create_folder(account_id: int, data: CreateFolderRequest, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
|
||||
import asyncio
|
||||
def _create():
|
||||
client = _get_imap_client(account)
|
||||
with client:
|
||||
return client.create_folder(data.folder_name)
|
||||
|
||||
try:
|
||||
success = await asyncio.to_thread(_create)
|
||||
if success:
|
||||
return {"success": True, "message": f"Ordner '{data.folder_name}' erstellt"}
|
||||
raise HTTPException(400, f"Ordner '{data.folder_name}' konnte nicht erstellt werden")
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"Fehler: {e}")
|
||||
|
||||
Reference in New Issue
Block a user