# CRM Server API Backend API pre email a kontaktný manažment s podporou viacerých JMAP účtov. ## Funkcie ### Autentifikácia - **Login** - Session-based auth s JWT tokens (httpOnly cookies) - **Onboarding** - 3-krokový flow (login → nastavenie hesla → pripojenie emailu) - **Session management** - Automatický refresh tokenov - **Role-based access** - Admin a Member ### Email účty (Multi-account) - **Pridanie účtu** - Pripojenie viacerých JMAP účtov - **Šifrovanie hesiel** - AES-256-GCM encryption pre JMAP heslá - **Primárny účet** - Označenie hlavného účtu - **Cascade delete** - Odstránenie účtu vymaže všetky jeho dáta ### JMAP Email integrácia - **Sync emailov** - Stiahnutie emailov z Truemail.sk JMAP servera - **Thread organizácia** - Emaily zoskupené do konverzácií - **Full-text search** - Vyhľadávanie v predmete, tele, odosielateľovi - **Posielanie odpovedí** - Odpoveď na emaily cez JMAP - **Neprecítané správy** - Počítadlo per účet ### Kontakty - **Objavovanie** - Automatické získanie odosielateľov z emailov - **Auto-sync emailov** - Pri pridaní kontaktu sa stiahnu všetky jeho emaily - **CRUD operácie** - Pridanie, úprava, odstránenie - **Account filtering** - Kontakty izolované per email účet ### Správa používateľov (Admin) - **Vytvorenie usera** - Auto-generovanie temporary hesla - **Zmena rolí** - Admin/Member - **Zoznam používateľov** - Len pre adminov ### Bezpečnosť - **Password hashing** - Bcrypt (12 rounds) - **Rate limiting** - Login, API, citlivé operácie - **Helmet** - HTTP security headers (CSP, HSTS) - **Input validation** - Zod schemas - **SQL injection protection** - Drizzle ORM prepared statements - **XSS protection** - Sanitizácia inputov - **Audit logging** - Všetky dôležité akcie logované ## API Endpointy ### Autentifikácia `/api/auth` - `POST /login` - Prihlásenie - `POST /set-password` - Nastavenie hesla (onboarding) - `POST /change-password` - Zmena hesla - `POST /logout` - Odhlásenie - `GET /session` - Získanie session info - `GET /me` - Aktuálny používateľ ### Email účty `/api/email-accounts` - `GET /` - Zoznam účtov - `POST /` - Pridanie účtu - `DELETE /:id` - Odstránenie účtu - `PATCH /:id/primary` - Nastavenie primárneho ### Admin `/api/admin` (Admin only) - `POST /users` - Vytvorenie používateľa - `GET /users` - Zoznam používateľov - `PATCH /users/:id/role` - Zmena role - `DELETE /users/:id` - Zmazanie používateľa ### Kontakty `/api/contacts` - `GET /` - Zoznam kontaktov (s accountId filtrom) - `GET /discover` - Potenciálne kontakty z JMAP - `POST /` - Pridať kontakt + auto-sync emailov - `PATCH /:id` - Upraviť kontakt - `DELETE /:id` - Odstrániť kontakt ### Emaily `/api/emails` - `GET /` - Zoznam emailov (s accountId filtrom) - `GET /search` - Vyhľadávanie v DB - `GET /search-jmap` - JMAP full-text search - `GET /thread/:id` - Thread konverzácie - `POST /thread/:id/read` - Označiť thread ako prečítaný - `POST /sync` - Manuálna synchronizácia - `POST /reply` - Odpovedať na email - `GET /unread-count` - Počet neprecítaných per účet ## Services ### auth.service.js Správa autentifikácie a používateľov. **Funkcie:** - `getUserById(id)` - Získanie usera z DB podľa ID - `getUserByUsername(username)` - Nájdenie usera podľa username - `createUser(data)` - Vytvorenie nového usera s auto-generovaným temporary heslom - `validatePassword(user, password)` - Validácia hesla (bcrypt compare s temp_password alebo password) - `changePassword(userId, newPassword)` - Zmena hesla + audit log + update `changed_password = true` - `updateLastLogin(userId)` - Update `last_login` timestamp ### email-account.service.js Multi-account email management. **Funkcie:** - `getEmailAccounts(userId)` - Zoznam všetkých email účtov usera - `addEmailAccount(userId, email, password)` - Pridanie JMAP účtu s validáciou credentials a šifrovaním hesla - `getEmailAccountWithCredentials(accountId, userId)` - Účet s dešifrovaným heslom (pre JMAP operácie) - `getPrimaryEmailAccount(userId)` - Vráti primárny účet usera - `removeEmailAccount(accountId, userId)` - Odstránenie účtu + cascade delete kontaktov a emailov - `setPrimaryAccount(accountId, userId)` - Nastavenie účtu ako primárneho (resetne ostatné) - `verifyAccountOwnership(accountId, userId)` - Overenie že účet patrí userovi ### jmap.service.js JMAP protokol integrácia s Truemail.sk. **Core funkcie:** - `jmapRequest(config, methodCalls)` - Low-level JMAP HTTP request (Basic Auth + JSON payload) - `getJmapSession(config)` - Získanie JMAP session (capabilities, accountId, upload URL) - `getJmapConfigFromAccount(accountId, userId)` - Vytvorenie JMAP config objektu z DB account **Email operácie:** - `syncEmailsFromJMAP(config, userId, accountId, filters)` - Stiahnutie emailov z JMAP a uloženie do DB - `syncEmailsFromSender(config, userId, accountId, senderEmail, contactId)` - Sync všetkých emailov od konkrétneho odosielateľa - `searchEmailsJMAP(config, query, limit, offset)` - Full-text search v JMAP serveri - `sendEmail(config, emailAccountId, to, subject, body, inReplyTo)` - Vytvorenie a poslanie odpovede cez JMAP - `markEmailAsRead(config, userId, jmapId, isRead)` - Update `$seen` keywordu na JMAP serveri **Discovery:** - `discoverContactsFromJMAP(config)` - Získanie všetkých unikátnych emailových adries z INBOX **Helpers:** - `parseJmapResponse(response)` - Parsovanie JMAP response a error handling - `extractEmailAddress(emailObject)` - Extrahovanie email adresy z JMAP formátu `[{email: "..."}]` ### contact.service.js Správa kontaktov s auto-sync funkciou. **Funkcie:** - `getUserContacts(userId, accountId?)` - Zoznam kontaktov usera (s voliteľným account filtrom) - `getContactById(contactId, userId)` - Detail kontaktu s ownership validáciou - `addContact(userId, accountId, email, name?, notes?)` - Pridanie kontaktu + **automatický sync emailov od tohto odosielateľa** - `updateContact(contactId, userId, updates)` - Update mena alebo poznámok - `removeContact(contactId, userId)` - Odstránenie kontaktu (emaily zostávajú, `contact_id = null`) - `verifyContactOwnership(contactId, userId)` - Overenie ownership ### crm-email.service.js Email CRUD operácie a thread management. **Funkcie:** - `getUserEmails(userId, accountId?, filters?)` - Zoznam emailov s pagination a filtrami (isRead, contactId, search) - `getEmailById(emailId, userId)` - Detail emailu - `getEmailThread(threadId, userId)` - Všetky emaily v konverzácii (sorted by date) - `markThreadAsRead(threadId, userId, isRead)` - Označenie všetkých emailov v threade - `searchEmails(userId, query, accountId?)` - DB full-text search (subject, body, from) - `getUnreadCount(userId, accountId?)` - Počet neprecítaných emailov per účet - `createEmail(data)` - Vytvorenie email záznamu v DB (používa jmap.service) - `updateEmailReadStatus(emailId, userId, isRead)` - Update single email read status ### audit.service.js Audit logging pre bezpečnostné účely. **Funkcia:** - `logAuditEvent(data)` - Zaloguje akciu do audit_logs tabuľky ```javascript { userId, action, resource, resourceId?, oldValue?, newValue?, success, errorMessage?, ipAddress?, userAgent? } ``` **Tracked events:** - Login (success/fail) - Password changes - User creation/deletion - Email account add/remove - Role changes - Contact add/remove ### email.service.js (Legacy?) Basic email operácie - možno deprecated v prospech crm-email.service.js ## Middlewares ### Autentifikácia **authenticate.js** - Validuje JWT access token z httpOnly cookie - Načíta usera z DB a priradí k `req.user` - Ak token expiroval, vráti 401 Unauthorized - Ak token chýba, vráti 401 Unauthorized **roleMiddleware.js** `requireAdmin` - Overí že user má `role = 'admin'` - Používa sa pred admin-only endpointmi - Vráti 403 Forbidden ak nie je admin `requireOwnerOrAdmin` - Overí že user je vlastník resource alebo admin - Používa sa napr. pri úprave vlastného profilu - Parameter: `resourceUserId` z req.params alebo req.body ### Bezpečnosť **rateLimiter.js** `loginRateLimiter` - Limit: 5 pokusov / 15 minút - Scope: Per IP adresa - Používa sa na `/api/auth/login` - Ochrana proti brute force útokom `apiRateLimiter` - Limit: 100 requestov / 15 min (production) - Limit: 1000 requestov / 15 min (development) - Scope: Per IP adresa - Aplikuje sa na všetky `/api/*` routes `sensitiveOperationLimiter` - Limit: 3 pokusy / 15 minút - Používa sa na password change, user delete, atď. - Extra ochrana pre kritické operácie **validateInput.js** - XSS sanitizácia vstupných dát - Používa `xss-clean` knižnicu - Automaticky aplikované cez `xss-clean` middleware ### Validácia **validateBody.js** - Middleware factory pre Zod schema validáciu - Použitie: `validateBody(schema)` - Pri validačnej chybe vráti 400 s detailmi **validateParams.js** - Validácia URL parametrov (napr. `:id`) - Zod schemas pre params **Príklad použitia:** ```javascript router.post( '/login', validateBody(loginSchema), loginRateLimiter, loginController ); ``` ### Global **errorHandler.js** - Centrálne spracovanie všetkých errorov - Rozpoznáva custom error classes (`BadRequestError`, `UnauthorizedError`, ...) - Production: Skryje stack traces - Development: Full error details - Loguje errory cez Winston **notFound.js** - 404 handler pre neexistujúce routes - Musí byť zaregistrovaný **pred** errorHandler - Vráti: `{ success: false, error: 'Route not found' }` ## Database Schema ### users - id, username, role (admin/member) - password, temp_password (bcrypt hash) - changed_password, last_login - created_at, updated_at ### email_accounts - id, user_id (FK → users) - email, email_password (AES-256 encrypted) - jmap_account_id - is_primary, is_active - created_at, updated_at ### contacts - id, user_id (FK → users) - email_account_id (FK → email_accounts) - email, name, notes - added_at, created_at, updated_at ### emails - id, user_id (FK → users) - email_account_id (FK → email_accounts) - contact_id (FK → contacts) - jmap_id, message_id, thread_id - from, to, subject, body - is_read, date - created_at, updated_at ### audit_logs - id, user_id (FK → users) - action, resource, resource_id - old_value, new_value (JSON) - ip_address, user_agent - success, error_message - created_at ## Konfigurácia ### Environment Variables (.env) ```env # Server Configuration PORT=5000 # Port na ktorom beží Express server NODE_ENV=development # development | production (ovplyvňuje rate limits, error handling) # Database Configuration DB_HOST=localhost # PostgreSQL host (docker-compose: 'postgres') DB_PORT=5432 # PostgreSQL port DB_USER=admin # DB username DB_PASSWORD=heslo123 # DB password DB_NAME=crm # Database name # JWT Secrets (MUSIA byť dlhé a náhodné!) JWT_SECRET=your-secret-key # Pre access token (min 32 znakov) JWT_REFRESH_SECRET=your-refresh-secret # Pre refresh token (min 32 znakov) JWT_EXPIRES_IN=1h # Access token expiration (1h = 1 hodina) # JMAP Configuration JMAP_SERVER=https://mail.truemail.sk/jmap/ # JMAP endpoint pre Truemail.sk # Encryption (pre JMAP heslá) ENCRYPTION_KEY=your-32-char-encryption-key # PRESNE 32 znakov pre AES-256 # CORS CORS_ORIGIN=http://localhost:5173 # Frontend URL (React dev server) # Optional BCRYPT_ROUNDS=12 # Bcrypt cost factor (default: 12) ``` ### Ako vygenerovať secrets **JWT_SECRET a JWT_REFRESH_SECRET:** ```bash node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" ``` **ENCRYPTION_KEY (presne 32 znakov):** ```bash node -e "console.log(require('crypto').randomBytes(32).toString('base64').slice(0, 32))" ``` ### Docker Compose **docker-compose.yml** obsahuje len PostgreSQL databázu: ```yaml services: postgres: image: postgres:16 container_name: postgres-db restart: "no" ports: - "5432:5432" volumes: - ./postgres:/var/lib/postgresql/data ``` **Spustenie:** ```bash docker-compose up -d postgres # Start databázy docker-compose down # Stop databázy (data zostanú) docker-compose down -v # Stop + vymazanie volumes (⚠️ stratíš dáta) ``` ### Drizzle Configuration **drizzle.config.js** - Konfigurácia pre Drizzle Kit (migrations tool): ```javascript { schema: './src/db/schema.js', // Kde je DB schema definovaná out: './src/db/migrations', // Kam sa uložia migrračné SQL súbory dialect: 'postgresql', dbCredentials: { /* z .env */ }, verbose: true, // Loguje SQL queries strict: true // Prísna validácia } ``` **Používané príkazy:** - `drizzle-kit generate` → vygeneruje SQL migrácie zo schémy - `drizzle-kit push` → pushne schému priamo (skip migrations) - `drizzle-kit studio` → otvorí DB GUI na http://localhost:4983 ## Skripty ### NPM Skripty ```bash # Development & Production npm run dev # Spustí vývojový server s nodemon (hot reload) npm start # Production server (bez reloadovania) # Database management npm run db:generate # Vygeneruje SQL migračné súbory z Drizzle schémy npm run db:migrate # Aplikuje migrácie na databázu npm run db:push # Pushne schému priamo (bez migračných súborov) npm run db:studio # Otvorí Drizzle Studio - GUI pre databázu # Seeding npm run db:seed # Vytvorí admin účet s náhodným heslom npm run db:seed:testuser # Vytvorí testovacieho usera (testuser/testuser123!) # Testing npm test # Spustí Jest testy ``` ### Utility Skripty **check-tables.js** - Zoznam všetkých tabuliek v databáze ```bash node check-tables.js ``` **test-search.js** - Test JMAP search endpointu (vyžaduje TEST_COOKIE env) ```bash TEST_COOKIE='session=xyz...' node test-search.js ``` **mark-email-read-jmap.js** - Označí konkrétny email ako prečítaný cez JMAP ```bash node mark-email-read-jmap.js ``` **scripts/encrypt-password.js** - Zašifruje heslo pre manuálne vloženie do DB ```bash node scripts/encrypt-password.js 'your-password' ``` ## Spustenie ### Prvý setup 1. **Nainštaluj dependencies** ```bash npm install ``` 2. **Skopíruj a nastav .env** ```bash cp .env.example .env ``` - Nastav `DB_*` credentials (default sú pre docker-compose) - Vygeneruj silný `JWT_SECRET` a `JWT_REFRESH_SECRET` - Vygeneruj 32-znakový `ENCRYPTION_KEY` (pre šifrovanie JMAP hesiel) - Nastav `CORS_ORIGIN` pre frontend (default: http://localhost:5173) 3. **Spusti PostgreSQL databázu** ```bash docker-compose up -d postgres ``` 4. **Aplikuj databázové migrácie** ```bash npm run db:migrate ``` 5. **Vytvor admin účet** ```bash npm run db:seed ``` ⚠️ **DÔLEŽITÉ:** Skopíruj si vygenerované temporary heslo! Budeš ho potrebovať pri prvom prihlásení. 6. **Spusti server** ```bash npm run dev ``` 7. **API beží na** `http://localhost:5000` - Health check: `GET /health` - API docs: Všetky endpointy sú popísané v sekcii "API Endpointy" ### Každodenný development ```bash # Spusti databázu (ak nie je spustená) docker-compose up -d postgres # Spusti dev server npm run dev # Otvor DB GUI (voliteľné) npm run db:studio ``` ## Ako to funguje ### Architektúra Aplikácia používa **layered architecture** so separáciou zodpovedností: ``` Client Request ↓ Routes (routing) ↓ Middlewares (auth, validation, rate limiting) ↓ Controllers (request handling, response formatting) ↓ Services (business logic) ↓ Database (Drizzle ORM) ``` ### Flow autentifikácie a onboardingu 1. **Admin vytvorí nového usera** - `POST /api/admin/users` s username, firstName, lastName, role - Systém vygeneruje náhodné temporary heslo (16 znakov, mix uppercase/lowercase/numbers/symbols) - Heslo sa hashuje bcryptom (12 rounds) a uloží do `temp_password` - `changed_password = false` 2. **Prvé prihlásenie** - User sa prihlási s temporary heslom: `POST /api/auth/login` - Backend zistí že `changed_password = false` a vráti flag `mustChangePassword: true` - Frontend redirectne na "set password" screen 3. **Nastavenie vlastného hesla** - `POST /api/auth/set-password` s novým heslom - Validácia: min 8 znakov, uppercase, lowercase, number, symbol - Heslo sa hashuje a uloží do `password` fieldu - `temp_password = null`, `changed_password = true` 4. **Session management** - Pri login dostane user JWT access token (httpOnly cookie, 1h) - Refresh token (httpOnly cookie, 7 dní) - Pri expirácii access tokenu sa automaticky refreshne ### Email synchronizácia flow 1. **Pripojenie email účtu** - User pridá JMAP účet: `POST /api/email-accounts` - Backend overí JMAP credentials volaním `getJmapSession()` - Heslo sa zašifruje AES-256-GCM a uloží do DB - JMAP accountId sa uloží pre budúce requesty 2. **Prvý sync** - Automaticky sa stiahnu emaily z INBOX - `Email/query` + `Email/get` JMAP volania - Emaily sa uložia do DB s `thread_id` pre organizáciu konverzácií 3. **Nepretržitý sync** - Frontend pravidelne volá `GET /api/emails?accountId=X` - Backend volá JMAP a stiahne nové emaily od posledného syncu - Update-uje `is_read` status podľa JMAP ### Kontakty a auto-sync 1. **Discovery kontaktov** - `GET /api/contacts/discover?accountId=X` - Backend stiahne všetky emaily z JMAP - Extrahuje unikátne email adresy z `from` a `to` polí - Vráti zoznam emailov ktoré ešte nie sú v kontaktoch 2. **Pridanie kontaktu** - `POST /api/contacts` s `email` a `emailAccountId` - Backend uloží kontakt do DB - **Auto-sync:** Automaticky vyhľadá všetky emaily od/pre tento kontakt cez JMAP - Stiahnuť a uloží všetky nájdené emaily s linknutím na kontakt (`contact_id`) 3. **Email thread organizácia** - Emaily sa zoskupujú podľa `thread_id` (z JMAP) - `GET /api/emails/thread/:threadId` vráti chronologickú konverzáciu - Mark as read označí všetky emaily v threade ### Bezpečnostné mechanizmy **Rate Limiting:** - Login: 5 pokusov / 15 min (brute force ochrana) - API: 100 requestov / 15 min (1000 v dev mode) - Sensitive operations: 3 pokusy / 15 min **Password Security:** - Bcrypt hashing s 12 rounds (2^12 = 4096 iterations) - Temporary passwords: 16 znakov, vysoká entropia - Validácia: min 8 znakov, mix typov znakov **Data Encryption:** - JMAP heslá: AES-256-GCM (symetrické šifrovanie) - Format: `iv:authTag:encryptedText` - Kľúč derivovaný z `ENCRYPTION_KEY` cez scrypt **Session Security:** - JWT tokeny v httpOnly cookies (XSS ochrana) - SameSite=Strict (CSRF ochrana) - Krátka platnosť access tokenu (1h) - Refresh token rotation **Input Validation:** - Zod schemas pre všetky endpointy - XSS sanitizácia cez xss-clean - SQL injection ochrana cez Drizzle ORM prepared statements **Audit Logging:** - Všetky dôležité akcie (login, password change, user creation, email account add/remove) - Ukladá user_id, action, resource, old/new values, IP, user-agent - `GET /api/admin/audit-logs` pre adminov ### Database Cascade Deletes **User Delete:** - Cascade vymaže: email_accounts → contacts → emails → audit_logs **Email Account Delete:** - Cascade vymaže: contacts → emails (pre tento účet) - User si môže pridať ďalší účet **Contact Delete:** - Emaily od tohto kontaktu zostávajú (len `contact_id = null`) - Možnosť filtrovať "orphaned" emaily ### JMAP Operácie **Supported operations:** 1. **Email/query** - Vyhľadávanie emailov ```javascript { filter: { inMailbox: 'inbox' }, sort: [{ property: 'receivedAt', isAscending: false }], limit: 50 } ``` 2. **Email/get** - Získanie detailov emailov ```javascript { ids: ['id1', 'id2'], properties: ['from', 'to', 'subject', 'bodyValues', 'threadId', ...] } ``` 3. **Email/set** - Vytvorenie emailu (draft) ```javascript { create: { draft1: { mailboxIds: { drafts: true }, from: [...], to: [...], subject: '...', bodyValues: { body: { value: '...' }} } } } ``` 4. **EmailSubmission/set** - Poslanie emailu ```javascript { create: { sub1: { emailId: 'draft1', identityId: 'identity1' } } } ``` 5. **Email/changes** - Incremental sync (delta updates) - Používa `sinceState` pre získanie len zmenených emailov - Optimalizované pre veľké mailboxy ### Šifrovanie JMAP hesiel **Encryption flow:** ```javascript // Encryption (pri pridaní účtu) 1. Vygeneruj náhodný IV (16 bytes) 2. Vytvor cipher s AES-256-GCM, key, IV 3. Zašifruj heslo 4. Získaj auth tag 5. Ulož: `${iv}:${authTag}:${encrypted}` // Decryption (pri JMAP operáciách) 1. Split stored value na [iv, authTag, encrypted] 2. Vytvor decipher s AES-256-GCM, key, IV 3. Nastav auth tag 4. Dešifruj heslo 5. Použij pre JMAP request ``` ### Multi-Account Management Každý user môže mať **viacero email účtov**: - Jeden je označený ako **primárny** (`is_primary = true`) - Kontakty a emaily sú **izolované per účet** (accountId filter) - Frontend prepína medzi účtami cez accountId parameter - Každý účet má vlastný JMAP session a credentials ### Error Handling **Centrálny error handler middleware:** - Všetky chyby idú cez `errorHandler.js` - Custom error classes: `BadRequestError`, `UnauthorizedError`, `NotFoundError`, `ConflictError` - Production mode: Skryje stack traces - Development mode: Full error details + stack trace - Všetky errory sa logujú cez Winston logger ## Systém rolí **Admin** - Všetko čo Member - `/api/admin/*` endpointy - Vytvorenie/zmazanie používateľov - Zmena rolí **Member** - Vlastný profil a nastavenia - Správa vlastných email účtov - Vlastné kontakty a emaily - Inbox ## JMAP Integrácia ### Provider: Truemail.sk **JMAP Endpoint:** `https://mail.truemail.sk/jmap/` **Autentifikácia:** Basic Auth - Username: email adresa (napr. `user@slovensko.ai`) - Password: email heslo (uložené encrypted v DB) ### JMAP Session Každý JMAP request začína získaním session: ```javascript GET https://mail.truemail.sk/jmap/session/ Authorization: Basic base64(email:password) Response: { "capabilities": { "urn:ietf:params:jmap:core": { maxObjectsInGet: 500, ... }, "urn:ietf:params:jmap:mail": { ... } }, "accounts": { "account-id": { "name": "user@slovensko.ai", "isPersonal": true, "accountCapabilities": { ... } } }, "primaryAccounts": { "urn:ietf:params:jmap:mail": "account-id" } } ``` `accountId` sa ukladá do DB (`jmap_account_id`) a používa pre všetky ďalšie requesty. ### Supported JMAP Methods **1. Email/query** - Vyhľadávanie emailov ```javascript [ "Email/query", { accountId: "account-id", filter: { inMailbox: "inbox", // alebo "sent", "drafts" from: "email@domain.sk" // voliteľný filter }, sort: [{ property: "receivedAt", isAscending: false }], limit: 50, position: 0 }, "call-id" ] Response: { list: ["emailId1", "emailId2", ...], total: 156 } ``` **2. Email/get** - Získanie detailov ```javascript [ "Email/get", { accountId: "account-id", ids: ["emailId1", "emailId2"], properties: [ "id", "threadId", "mailboxIds", "keywords", "from", "to", "cc", "bcc", "subject", "receivedAt", "bodyValues", "textBody", "htmlBody" ], bodyProperties: ["partId", "type", "value"] }, "call-id" ] Response: { list: [{ id: "emailId1", from: [{ email: "sender@domain.sk", name: "Sender Name" }], subject: "Email subject", bodyValues: { body: { value: "Email content..." } }, ... }] } ``` **3. Email/set** - Vytvorenie/Update/Delete ```javascript // Vytvorenie draft emailu [ "Email/set", { accountId: "account-id", create: { "draft-1": { mailboxIds: { "drafts-mailbox-id": true }, from: [{ email: "me@slovensko.ai" }], to: [{ email: "recipient@domain.sk" }], subject: "Reply subject", bodyValues: { body: { value: "Email content", type: "text/plain" } }, textBody: [{ partId: "body", type: "text/plain" }], keywords: { "$draft": true } } } }, "call-id" ] // Update (napr. mark as read) [ "Email/set", { accountId: "account-id", update: { "emailId1": { "keywords/$seen": true // mark as read } } }, "call-id" ] ``` **4. EmailSubmission/set** - Poslanie emailu ```javascript [ "EmailSubmission/set", { accountId: "account-id", create: { "submission-1": { emailId: "draft-1", // ID z Email/set create identityId: "identity-id", // Z Identity/get envelope: { mailFrom: { email: "me@slovensko.ai" }, rcptTo: [{ email: "recipient@domain.sk" }] } } } }, "call-id" ] ``` **5. Mailbox/get** - Zoznam mailboxov (INBOX, Sent, Drafts, ...) ```javascript [ "Mailbox/get", { accountId: "account-id", ids: null // null = všetky }, "call-id" ] Response: { list: [ { id: "inbox-id", name: "Inbox", role: "inbox", ... }, { id: "sent-id", name: "Sent", role: "sent", ... } ] } ``` **6. Identity/get** - Email identity (pre sending) ```javascript [ "Identity/get", { accountId: "account-id", ids: null }, "call-id" ] Response: { list: [{ id: "identity-id", email: "me@slovensko.ai", name: "My Name" }] } ``` **7. Email/changes** - Delta sync (incremental updates) ```javascript [ "Email/changes", { accountId: "account-id", sinceState: "previous-state-token", maxChanges: 100 }, "call-id" ] Response: { oldState: "previous-state", newState: "current-state", hasMoreChanges: false, created: ["emailId1"], updated: ["emailId2"], destroyed: ["emailId3"] } ``` ### JMAP Request Format Všetky requesty používajú rovnaký formát: ```javascript POST https://mail.truemail.sk/jmap/api/ Authorization: Basic base64(email:password) Content-Type: application/json { "using": [ "urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail" ], "methodCalls": [ ["Method/name", { params }, "call-id"], ... ] } ``` ### Error Handling JMAP errory majú formát: ```javascript { "methodResponses": [ ["error", { "type": "invalidArguments", "description": "Invalid filter" }, "call-id"] ] } ``` **Common error types:** - `invalidArguments` - Zlé parametre - `accountNotFound` - Neplatný accountId - `notFound` - Email/mailbox nenájdený - `forbidden` - Nedostatočné oprávnenia - `serverFail` - Server error ### Optimalizácie **Batching:** - Jeden HTTP request môže obsahovať viacero method calls - Príklad: Email/query + Email/get v jednom requeste **Result References:** - Výsledok jedného method callu môže byť použitý v ďalšom - Príklad: Email/query → Email/get s `#ids` referenciou **Incremental Sync:** - Používaj `Email/changes` namiesto full Email/query - Ukladaj `state` token pre ďalšie syncs - Znižuje bandwidth a load ## Šifrovanie **JMAP heslá** - AES-256-GCM - Format: `iv:authTag:encryptedText` - Kľúč: `ENCRYPTION_KEY` z .env (32 znakov) - Funkcie: `encryptPassword()`, `decryptPassword()` **User heslá** - Bcrypt - 12 rounds (2^12 iterations) - Funkcie: `hashPassword()`, `comparePassword()`