update docs

This commit is contained in:
richardtekula
2025-11-19 13:21:34 +01:00
parent 1e7c1eab90
commit 51714c8edd

885
README.md
View File

@@ -85,61 +85,180 @@ Backend API pre email a kontaktný manažment s podporou viacerých JMAP účtov
## Services
### auth.service.js
- `getUserById()` - Získanie usera z DB
- `createUser()` - Vytvorenie nového usera s temp heslom
- `validatePassword()` - Validácia hesla (bcrypt compare)
- `changePassword()` - Zmena hesla s auditom
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
- `getEmailAccounts()` - Zoznam účtov pre usera
- `addEmailAccount()` - Pridanie JMAP účtu (šifrovanie hesla)
- `getEmailAccountWithCredentials()` - Účet s dešifrovaným heslom
- `getPrimaryEmailAccount()` - Primárny účet
- `removeEmailAccount()` - Odstránenie s cascade delete
- `setPrimaryAccount()` - Nastavenie primárneho
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
- `jmapRequest()` - HTTP request na JMAP server
- `getJmapSession()` - Získanie JMAP session
- `getJmapConfigFromAccount()` - Config z email účtu
- `syncEmailsFromSender()` - Sync emailov od kontaktu
- `searchEmailsJMAP()` - Full-text search v JMAP
- `sendEmail()` - Poslanie odpovede cez JMAP
- `discoverContactsFromJMAP()` - Objavenie odosielateľov
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
- `getUserContacts()` - Kontakty usera (s accountId filtrom)
- `addContact()` - Pridanie + auto-sync emailov
- `updateContact()` - Úprava kontaktu
- `removeContact()` - Odstránenie + cascade delete
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
- `getUserEmails()` - Emaily usera (s accountId filtrom)
- `getEmailThread()` - Thread konverzácia
- `markThreadAsRead()` - Označenie threadu
- `searchEmails()` - DB vyhľadávanie
- `getUnreadCount()` - Počet neprecítaných per účet
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
- `logAuditEvent()` - Zaloguje akciu s IP, user-agent, timestamp
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` - Validácia JWT tokenu, načítanie usera
- `requireAdmin` - Overenie admin role
- `requireOwnerOrAdmin` - Vlastník alebo admin
**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ť
- `loginRateLimiter` - 5 pokusov / 15 min
- `apiRateLimiter` - 100 requestov / 15 min (dev: 1000)
- `sensitiveOperationLimiter` - 3 pokusy / 15 min
- `validateBody` - Zod schema validácia
- `validateParams` - Zod params validácia
**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` - Centrálne error handling
- `notFound` - 404 handler
**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
@@ -181,56 +300,404 @@ Backend API pre email a kontaktný manažment s podporou viacerých JMAP účtov
## Konfigurácia
**.env**
### Environment Variables (.env)
```env
# Server
PORT=5000
NODE_ENV=development
# Server Configuration
PORT=5000 # Port na ktorom beží Express server
NODE_ENV=development # development | production (ovplyvňuje rate limits, error handling)
# Database
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=password
DB_NAME=crm
# 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
JWT_SECRET=your-secret-key
JWT_REFRESH_SECRET=your-refresh-secret
JWT_EXPIRES_IN=1h
# 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
JMAP_SERVER=https://mail.truemail.sk/jmap/
# JMAP Configuration
JMAP_SERVER=https://mail.truemail.sk/jmap/ # JMAP endpoint pre Truemail.sk
# Encryption
ENCRYPTION_KEY=your-32-char-encryption-key
# Encryption (pre JMAP heslá)
ENCRYPTION_KEY=your-32-char-encryption-key # PRESNE 32 znakov pre AES-256
# CORS
CORS_ORIGIN=http://localhost:5173
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
npm run dev # Dev server s nodemon
npm start # Production server
npm run db:generate # Generovanie Drizzle migrácií
npm run db:migrate # Aplikovanie migrácií
npm run db:push # Push schema (bez migrácií)
npm run db:studio # Drizzle Studio (DB GUI)
npm run db:seed # Seed admin account
npm test # Spustenie testov
# 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
1. Nainštaluj dependencies: `npm install`
2. Nastav `.env` s DB credentials a secrets
3. Spusti PostgreSQL: `docker-compose up -d postgres`
4. Aplikuj migrácie: `npm run db:migrate`
5. Seed admin: `npm run db:seed` (uložíš si temp password!)
6. Spusti server: `npm run dev`
7. API beží na `http://localhost:5000`
### 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í
@@ -248,16 +715,272 @@ npm test # Spustenie testov
## JMAP Integrácia
- **Provider:** Truemail.sk
- **Endpoint:** https://mail.truemail.sk/jmap/
- **Auth:** Basic Auth (email + heslo)
- **Operácie:**
- Email/query - Vyhľadávanie emailov
- Email/get - Získanie detailov
- Email/set - Vytvorenie emailu
- EmailSubmission/set - Poslanie emailu
- Mailbox/get - Zoznam mailboxov
- Identity/get - Email identity
### 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