feat: mail phase 4 - IMAP folder create/delete + auto-sync

- Add imap_create_folder() and imap_delete_folder() service functions
- Call IMAP CREATE/DELETE in folder create/delete endpoints
- Add auto_sync_all_accounts() background task (every 5 min)
- Start auto-sync loop on plugin activation via asyncio.create_task
- Frontend: working sync button with isSyncing state and toast feedback
- i18n: syncSuccess, syncFailed, syncing, autoSyncEnabled keys (de/en)
This commit is contained in:
Agent Zero
2026-07-15 20:28:11 +02:00
parent 4e100e9d33
commit f1a12092a0
6 changed files with 255 additions and 5 deletions
+44
View File
@@ -2,13 +2,32 @@
from __future__ import annotations
import asyncio
import logging
from app.plugins.base import BasePlugin
from app.plugins.manifest import PluginManifest, PluginRouteDef
logger = logging.getLogger(__name__)
async def _auto_sync_loop() -> None:
"""Background loop: sync all active mail accounts every 5 minutes."""
from app.plugins.builtins.mail.services import auto_sync_all_accounts
while True:
try:
await auto_sync_all_accounts()
except Exception as exc:
logger.warning("auto_sync error: %s", exc)
await asyncio.sleep(300)
class MailPlugin(BasePlugin):
"""Mail plugin for email management: IMAP sync, SMTP send, threading, rules, PGP."""
_auto_sync_task: asyncio.Task | None = None
manifest = PluginManifest(
name="mail",
version="1.0.0",
@@ -29,3 +48,28 @@ class MailPlugin(BasePlugin):
migrations=["0001_initial.sql"],
permissions=[],
)
async def on_activate(
self, db, service_container, event_bus
) -> None:
"""Activate plugin: register events + start auto-sync background task."""
await super().on_activate(db, service_container, event_bus)
if self._auto_sync_task is None or self._auto_sync_task.done():
self._auto_sync_task = asyncio.create_task(_auto_sync_loop())
logger.info("Mail plugin: auto-sync background task started")
async def on_deactivate(
self, db, service_container, event_bus
) -> None:
"""Deactivate plugin: stop auto-sync task + unregister events."""
if self._auto_sync_task is not None and not self._auto_sync_task.done():
self._auto_sync_task.cancel()
try:
await self._auto_sync_task
except asyncio.CancelledError:
pass
self._auto_sync_task = None
logger.info("Mail plugin: auto-sync background task stopped")
await super().on_deactivate(db, service_container, event_bus)