Initial commit: IMAP Mail Filter Service
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
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.schemas.schemas import (
|
||||
AccountCreate,
|
||||
AccountListResponse,
|
||||
AccountResponse,
|
||||
AccountUpdate,
|
||||
)
|
||||
from app.services.encryption import decrypt, encrypt
|
||||
from app.services.imap_client import async_test_connection
|
||||
|
||||
router = APIRouter(prefix="/api/accounts", tags=["accounts"])
|
||||
|
||||
|
||||
@router.get("/", response_model=list[AccountListResponse])
|
||||
def list_accounts(db: Session = Depends(get_db)):
|
||||
accounts = db.query(Account).order_by(Account.name).all()
|
||||
result = []
|
||||
for acc in accounts:
|
||||
data = AccountListResponse.model_validate(acc)
|
||||
data.filter_rule_count = len(acc.filter_rules)
|
||||
result.append(data)
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/{account_id}", response_model=AccountResponse)
|
||||
def get_account(account_id: int, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
return account
|
||||
|
||||
|
||||
@router.post("/", response_model=AccountResponse, status_code=201)
|
||||
def create_account(data: AccountCreate, db: Session = Depends(get_db)):
|
||||
account_data = data.model_dump()
|
||||
account_data["password"] = encrypt(account_data["password"])
|
||||
if account_data.get("smtp_password"):
|
||||
account_data["smtp_password"] = encrypt(account_data["smtp_password"])
|
||||
account = Account(**account_data)
|
||||
db.add(account)
|
||||
db.commit()
|
||||
db.refresh(account)
|
||||
return account
|
||||
|
||||
|
||||
@router.put("/{account_id}", response_model=AccountResponse)
|
||||
def update_account(account_id: int, data: AccountUpdate, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
for key, value in data.model_dump(exclude_unset=True).items():
|
||||
if key == "password" and value:
|
||||
value = encrypt(value)
|
||||
elif key == "smtp_password" and value:
|
||||
value = encrypt(value)
|
||||
setattr(account, key, value)
|
||||
db.commit()
|
||||
db.refresh(account)
|
||||
return account
|
||||
|
||||
|
||||
@router.delete("/{account_id}", status_code=204)
|
||||
def delete_account(account_id: int, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
db.delete(account)
|
||||
db.commit()
|
||||
|
||||
|
||||
@router.post("/{account_id}/test")
|
||||
async def test_account_connection(account_id: int, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
success = await async_test_connection(
|
||||
host=account.imap_host,
|
||||
port=account.imap_port,
|
||||
username=account.username,
|
||||
password=decrypt(account.password),
|
||||
use_ssl=account.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)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
from app.services.scheduler import poll_account
|
||||
await poll_account(account_id)
|
||||
return {"message": f"Polling für '{account.name}' durchgeführt"}
|
||||
@@ -0,0 +1,112 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.database import get_db
|
||||
from app.models.db_models import Account, FilterAction, FilterCondition, FilterRule
|
||||
from app.schemas.schemas import FilterRuleCreate, FilterRuleResponse, FilterRuleUpdate
|
||||
|
||||
router = APIRouter(prefix="/api/filters", tags=["filters"])
|
||||
|
||||
|
||||
@router.get("/account/{account_id}", response_model=list[FilterRuleResponse])
|
||||
def list_filters(account_id: int, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
rules = (
|
||||
db.query(FilterRule)
|
||||
.filter(FilterRule.account_id == account_id)
|
||||
.order_by(FilterRule.priority)
|
||||
.all()
|
||||
)
|
||||
return rules
|
||||
|
||||
|
||||
@router.get("/{rule_id}", response_model=FilterRuleResponse)
|
||||
def get_filter(rule_id: int, db: Session = Depends(get_db)):
|
||||
rule = db.get(FilterRule, rule_id)
|
||||
if not rule:
|
||||
raise HTTPException(404, "Filterregel nicht gefunden")
|
||||
return rule
|
||||
|
||||
|
||||
@router.post("/", response_model=FilterRuleResponse, status_code=201)
|
||||
def create_filter(data: FilterRuleCreate, db: Session = Depends(get_db)):
|
||||
account = db.get(Account, data.account_id)
|
||||
if not account:
|
||||
raise HTTPException(404, "Konto nicht gefunden")
|
||||
|
||||
rule = FilterRule(
|
||||
account_id=data.account_id,
|
||||
name=data.name,
|
||||
priority=data.priority,
|
||||
enabled=data.enabled,
|
||||
stop_processing=data.stop_processing,
|
||||
source_folder=data.source_folder,
|
||||
)
|
||||
db.add(rule)
|
||||
db.flush()
|
||||
|
||||
for cond_data in data.conditions:
|
||||
cond = FilterCondition(rule_id=rule.id, **cond_data.model_dump())
|
||||
db.add(cond)
|
||||
for action_data in data.actions:
|
||||
action = FilterAction(rule_id=rule.id, **action_data.model_dump())
|
||||
db.add(action)
|
||||
|
||||
db.commit()
|
||||
db.refresh(rule)
|
||||
return rule
|
||||
|
||||
|
||||
@router.put("/{rule_id}", response_model=FilterRuleResponse)
|
||||
def update_filter(rule_id: int, data: FilterRuleUpdate, db: Session = Depends(get_db)):
|
||||
rule = db.get(FilterRule, rule_id)
|
||||
if not rule:
|
||||
raise HTTPException(404, "Filterregel nicht gefunden")
|
||||
|
||||
update_data = data.model_dump(exclude_unset=True)
|
||||
|
||||
# Update conditions if provided
|
||||
if "conditions" in update_data:
|
||||
for cond in rule.conditions:
|
||||
db.delete(cond)
|
||||
for cond_data in data.conditions:
|
||||
cond = FilterCondition(rule_id=rule.id, **cond_data.model_dump())
|
||||
db.add(cond)
|
||||
del update_data["conditions"]
|
||||
|
||||
# Update actions if provided
|
||||
if "actions" in update_data:
|
||||
for action in rule.actions:
|
||||
db.delete(action)
|
||||
for action_data in data.actions:
|
||||
action = FilterAction(rule_id=rule.id, **action_data.model_dump())
|
||||
db.add(action)
|
||||
del update_data["actions"]
|
||||
|
||||
for key, value in update_data.items():
|
||||
setattr(rule, key, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(rule)
|
||||
return rule
|
||||
|
||||
|
||||
@router.delete("/{rule_id}", status_code=204)
|
||||
def delete_filter(rule_id: int, db: Session = Depends(get_db)):
|
||||
rule = db.get(FilterRule, rule_id)
|
||||
if not rule:
|
||||
raise HTTPException(404, "Filterregel nicht gefunden")
|
||||
db.delete(rule)
|
||||
db.commit()
|
||||
|
||||
|
||||
@router.put("/reorder/{account_id}")
|
||||
def reorder_filters(account_id: int, rule_ids: list[int], db: Session = Depends(get_db)):
|
||||
for priority, rule_id in enumerate(rule_ids):
|
||||
rule = db.get(FilterRule, rule_id)
|
||||
if rule and rule.account_id == account_id:
|
||||
rule.priority = priority
|
||||
db.commit()
|
||||
return {"message": "Reihenfolge aktualisiert"}
|
||||
@@ -0,0 +1,21 @@
|
||||
from fastapi import APIRouter, Depends, UploadFile
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.database import get_db
|
||||
from app.services.yaml_service import export_to_yaml, import_from_yaml
|
||||
|
||||
router = APIRouter(prefix="/api/yaml", tags=["yaml"])
|
||||
|
||||
|
||||
@router.get("/export", response_class=PlainTextResponse)
|
||||
def yaml_export(db: Session = Depends(get_db)):
|
||||
return export_to_yaml(db)
|
||||
|
||||
|
||||
@router.post("/import")
|
||||
async def yaml_import(file: UploadFile, db: Session = Depends(get_db)):
|
||||
content = await file.read()
|
||||
yaml_str = content.decode("utf-8")
|
||||
result = import_from_yaml(yaml_str, db)
|
||||
return result
|
||||
Reference in New Issue
Block a user