- Create todo_users junction table for many-to-many relationship - Add migration to create todo_users table and migrate existing data - Update validators to accept assignedUserIds array instead of assignedTo - Update todo service to handle multiple user assignments - Fetch and return assigned users with each TODO 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
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áseniePOST /set-password- Nastavenie hesla (onboarding)POST /change-password- Zmena heslaPOST /logout- OdhlásenieGET /session- Získanie session infoGET /me- Aktuálny používateľ
Email účty /api/email-accounts
GET /- Zoznam účtovPOST /- Pridanie účtuDELETE /:id- Odstránenie účtuPATCH /:id/primary- Nastavenie primárneho
Admin /api/admin (Admin only)
POST /users- Vytvorenie používateľaGET /users- Zoznam používateľovPATCH /users/:id/role- Zmena roleDELETE /users/:id- Zmazanie používateľa
Kontakty /api/contacts
GET /- Zoznam kontaktov (s accountId filtrom)GET /discover- Potenciálne kontakty z JMAPPOST /- Pridať kontakt + auto-sync emailovPATCH /:id- Upraviť kontaktDELETE /:id- Odstrániť kontakt
Emaily /api/emails
GET /- Zoznam emailov (s accountId filtrom)GET /search- Vyhľadávanie v DBGET /search-jmap- JMAP full-text searchGET /thread/:id- Thread konverzáciePOST /thread/:id/read- Označiť thread ako prečítanýPOST /sync- Manuálna synchronizáciaPOST /reply- Odpovedať na emailGET /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 IDgetUserByUsername(username)- Nájdenie usera podľa usernamecreateUser(data)- Vytvorenie nového usera s auto-generovaným temporary heslomvalidatePassword(user, password)- Validácia hesla (bcrypt compare s temp_password alebo password)changePassword(userId, newPassword)- Zmena hesla + audit log + updatechanged_password = trueupdateLastLogin(userId)- Updatelast_logintimestamp
email-account.service.js
Multi-account email management.
Funkcie:
getEmailAccounts(userId)- Zoznam všetkých email účtov useraaddEmailAccount(userId, email, password)- Pridanie JMAP účtu s validáciou credentials a šifrovaním heslagetEmailAccountWithCredentials(accountId, userId)- Účet s dešifrovaným heslom (pre JMAP operácie)getPrimaryEmailAccount(userId)- Vráti primárny účet useraremoveEmailAccount(accountId, userId)- Odstránenie účtu + cascade delete kontaktov a emailovsetPrimaryAccount(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 DBsyncEmailsFromSender(config, userId, accountId, senderEmail, contactId)- Sync všetkých emailov od konkrétneho odosielateľasearchEmailsJMAP(config, query, limit, offset)- Full-text search v JMAP serverisendEmail(config, emailAccountId, to, subject, body, inReplyTo)- Vytvorenie a poslanie odpovede cez JMAPmarkEmailAsRead(config, userId, jmapId, isRead)- Update$seenkeywordu 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 handlingextractEmailAddress(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áciouaddContact(userId, accountId, email, name?, notes?)- Pridanie kontaktu + automatický sync emailov od tohto odosielateľaupdateContact(contactId, userId, updates)- Update mena alebo poznámokremoveContact(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 emailugetEmailThread(threadId, userId)- Všetky emaily v konverzácii (sorted by date)markThreadAsRead(threadId, userId, isRead)- Označenie všetkých emailov v threadesearchEmails(userId, query, accountId?)- DB full-text search (subject, body, from)getUnreadCount(userId, accountId?)- Počet neprecítaných emailov per účetcreateEmail(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{ 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:
resourceUserIdz 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-cleanknižnicu - Automaticky aplikované cez
xss-cleanmiddleware
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:
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)
# 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:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY (presne 32 znakov):
node -e "console.log(require('crypto').randomBytes(32).toString('base64').slice(0, 32))"
Docker Compose
docker-compose.yml obsahuje len PostgreSQL databázu:
services:
postgres:
image: postgres:16
container_name: postgres-db
restart: "no"
ports:
- "5432:5432"
volumes:
- ./postgres:/var/lib/postgresql/data
Spustenie:
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):
{
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émydrizzle-kit push→ pushne schému priamo (skip migrations)drizzle-kit studio→ otvorí DB GUI na http://localhost:4983
Skripty
NPM Skripty
# 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
node check-tables.js
test-search.js - Test JMAP search endpointu (vyžaduje TEST_COOKIE env)
TEST_COOKIE='session=xyz...' node test-search.js
mark-email-read-jmap.js - Označí konkrétny email ako prečítaný cez JMAP
node mark-email-read-jmap.js
scripts/encrypt-password.js - Zašifruje heslo pre manuálne vloženie do DB
node scripts/encrypt-password.js 'your-password'
Spustenie
Prvý setup
-
Nainštaluj dependencies
npm install -
Skopíruj a nastav .env
cp .env.example .env- Nastav
DB_*credentials (default sú pre docker-compose) - Vygeneruj silný
JWT_SECRETaJWT_REFRESH_SECRET - Vygeneruj 32-znakový
ENCRYPTION_KEY(pre šifrovanie JMAP hesiel) - Nastav
CORS_ORIGINpre frontend (default: http://localhost:5173)
- Nastav
-
Spusti PostgreSQL databázu
docker-compose up -d postgres -
Aplikuj databázové migrácie
npm run db:migrate -
Vytvor admin účet
npm run db:seed⚠️ DÔLEŽITÉ: Skopíruj si vygenerované temporary heslo! Budeš ho potrebovať pri prvom prihlásení.
-
Spusti server
npm run dev -
API beží na
http://localhost:5000- Health check:
GET /health - API docs: Všetky endpointy sú popísané v sekcii "API Endpointy"
- Health check:
Každodenný development
# 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
-
Admin vytvorí nového usera
POST /api/admin/userss 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
-
Prvé prihlásenie
- User sa prihlási s temporary heslom:
POST /api/auth/login - Backend zistí že
changed_password = falsea vráti flagmustChangePassword: true - Frontend redirectne na "set password" screen
- User sa prihlási s temporary heslom:
-
Nastavenie vlastného hesla
POST /api/auth/set-passwords novým heslom- Validácia: min 8 znakov, uppercase, lowercase, number, symbol
- Heslo sa hashuje a uloží do
passwordfieldu temp_password = null,changed_password = true
-
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
-
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
- User pridá JMAP účet:
-
Prvý sync
- Automaticky sa stiahnu emaily z INBOX
Email/query+Email/getJMAP volania- Emaily sa uložia do DB s
thread_idpre organizáciu konverzácií
-
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_readstatus podľa JMAP
- Frontend pravidelne volá
Kontakty a auto-sync
-
Discovery kontaktov
GET /api/contacts/discover?accountId=X- Backend stiahne všetky emaily z JMAP
- Extrahuje unikátne email adresy z
fromatopolí - Vráti zoznam emailov ktoré ešte nie sú v kontaktoch
-
Pridanie kontaktu
POST /api/contactssemailaemailAccountId- 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)
-
Email thread organizácia
- Emaily sa zoskupujú podľa
thread_id(z JMAP) GET /api/emails/thread/:threadIdvráti chronologickú konverzáciu- Mark as read označí všetky emaily v threade
- Emaily sa zoskupujú podľa
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_KEYcez 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-logspre 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:
-
Email/query - Vyhľadávanie emailov
{ filter: { inMailbox: 'inbox' }, sort: [{ property: 'receivedAt', isAscending: false }], limit: 50 } -
Email/get - Získanie detailov emailov
{ ids: ['id1', 'id2'], properties: ['from', 'to', 'subject', 'bodyValues', 'threadId', ...] } -
Email/set - Vytvorenie emailu (draft)
{ create: { draft1: { mailboxIds: { drafts: true }, from: [...], to: [...], subject: '...', bodyValues: { body: { value: '...' }} } } } -
EmailSubmission/set - Poslanie emailu
{ create: { sub1: { emailId: 'draft1', identityId: 'identity1' } } } -
Email/changes - Incremental sync (delta updates)
- Používa
sinceStatepre získanie len zmenených emailov - Optimalizované pre veľké mailboxy
- Používa
Šifrovanie JMAP hesiel
Encryption flow:
// 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:
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
[
"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
[
"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
// 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
[
"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, ...)
[
"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)
[
"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)
[
"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:
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:
{
"methodResponses": [
["error", {
"type": "invalidArguments",
"description": "Invalid filter"
}, "call-id"]
]
}
Common error types:
invalidArguments- Zlé parametreaccountNotFound- Neplatný accountIdnotFound- Email/mailbox nenájdenýforbidden- Nedostatočné oprávneniaserverFail- 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
#idsreferenciou
Incremental Sync:
- Používaj
Email/changesnamiesto full Email/query - Ukladaj
statetoken pre ďalšie syncs - Znižuje bandwidth a load
Šifrovanie
JMAP heslá - AES-256-GCM
- Format:
iv:authTag:encryptedText - Kľúč:
ENCRYPTION_KEYz .env (32 znakov) - Funkcie:
encryptPassword(),decryptPassword()
User heslá - Bcrypt
- 12 rounds (2^12 iterations)
- Funkcie:
hashPassword(),comparePassword()