229 lines
9.1 KiB
JSON
229 lines
9.1 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "/schema/mailboxes",
|
|
"title": "Mailbox - External email account (multi-provider)",
|
|
"description": "A mailbox is an external email account (provider imap/pop3) attached to a tribe for synchronisation. Mailbox documents and their password secret live in the attached tribe namespace ({DATAPATH}/{tribe}/objects/mailboxes/itm and .../secrets). Synchronised mails are stored in the objects/mails collection of the same tribe. mailboxid stays globally unique across all tribes so a mailbox is resolvable by id. Passwords are never stored in the document: the password secret is stored separately at {DATAPATH}/{tribe}/objects/mailboxes/secrets/{mailboxid}.json (chmod 600). GRANULAR ACCESS: per-mailbox virtual profiles 'mail-{mailboxid}-reader' (read only) and 'mail-{mailboxid}-writer' (read + actions read/unread/trash) are added to the 'profils' array of the person document of the granted alias INSIDE the attached tribe. The model provides helpers setAccess/removeAccess to manage these profiles. APX3 BILLING: creating a mailbox requires the APX3 payment agreement and a declared weekly volume stored in the 'apx3' object. SYNC WATERMARK: a sync only fetches messages beyond the stored per-folder high-watermark 'syncCursor' instead of re-reading the N newest remote ids on every poll, and the 'syncing' marker prevents concurrent provider syncs when several users press sync at the same time.",
|
|
"type": "object",
|
|
"required": [
|
|
"mailboxid",
|
|
"provider",
|
|
"email",
|
|
"tribe"
|
|
],
|
|
"additionalProperties": false,
|
|
"apxid": "mailboxid",
|
|
"apxuniquekey": [
|
|
"mailboxid"
|
|
],
|
|
"apxidx": [
|
|
{
|
|
"name": "lst_mailboxid",
|
|
"type": "array",
|
|
"keyval": "mailboxid"
|
|
},
|
|
{
|
|
"name": "by_tribe",
|
|
"type": "distribution",
|
|
"keyval": "tribe"
|
|
},
|
|
{
|
|
"name": "by_status",
|
|
"type": "distribution",
|
|
"keyval": "status"
|
|
}
|
|
],
|
|
"apxaccessrights": {
|
|
"druids": {
|
|
"C": [],
|
|
"R": [],
|
|
"U": [],
|
|
"D": []
|
|
}
|
|
},
|
|
"properties": {
|
|
"mailboxid": {
|
|
"type": "string",
|
|
"description": "Unique slug identifier generated from label/email"
|
|
},
|
|
"provider": {
|
|
"type": "string",
|
|
"enum": ["imap", "pop3"],
|
|
"description": "Email provider: imap (password), pop3 (password)"
|
|
},
|
|
"connector": {
|
|
"type": "object",
|
|
"description": "Provider connection settings (public, never contains secrets). Passwords live in the secrets file.",
|
|
"properties": {
|
|
"host": { "type": "string", "description": "IMAP/POP3 server host" },
|
|
"port": { "type": "number", "description": "IMAP/POP3 server port (default 993/995)" },
|
|
"tls": { "type": "boolean", "default": true },
|
|
"user": { "type": "string", "description": "Login username (IMAP/POP3/SMTP)" },
|
|
"folder": { "type": "string", "description": "IMAP folder to poll (default INBOX)" },
|
|
"trashFolder": { "type": "string", "description": "IMAP folder receiving trashed messages" },
|
|
"sentFolder": { "type": "string", "description": "IMAP folder holding sent messages. Auto-detected ([Gmail]/Sent Mail on gmail.com hosts, Sent otherwise), overridable per mailbox. Corresponds to the app-side 'apxtriSent' folder." },
|
|
"deleteOnDownload": { "type": "boolean", "description": "POP3: delete remote message after download (also used by trash)" },
|
|
"rejectUnauthorized": { "type": "boolean", "default": true },
|
|
"smtp": {
|
|
"type": "object",
|
|
"description": "Outbound SMTP settings (nodemailer)",
|
|
"properties": {
|
|
"host": { "type": "string" },
|
|
"port": { "type": "number" },
|
|
"tls": { "type": "boolean", "default": true }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"connected": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "True when the last live test succeeded"
|
|
},
|
|
"lastTest": {
|
|
"type": ["object", "null"],
|
|
"description": "Result of the last provider connection test",
|
|
"properties": {
|
|
"ok": { "type": "boolean" },
|
|
"latency": { "type": ["number", "null"] },
|
|
"smtp": { "type": ["string", "null"] },
|
|
"dt": { "type": ["string", "null"] },
|
|
"error": { "type": ["string", "null"] }
|
|
}
|
|
},
|
|
"lastError": {
|
|
"type": "string",
|
|
"description": "Last synchronisation error message (empty when last sync succeeded)"
|
|
},
|
|
"lastErrorAt": {
|
|
"type": ["string", "null"],
|
|
"description": "When the last sync error occurred"
|
|
},
|
|
"email": {
|
|
"type": "string",
|
|
"format": "email"
|
|
},
|
|
"label": {
|
|
"type": "string"
|
|
},
|
|
"tribe": {
|
|
"type": "string",
|
|
"description": "Tribe where the synchronised mails are stored and where reader/writer person profiles are managed"
|
|
},
|
|
"syncMode": {
|
|
"type": "string",
|
|
"enum": ["poll"],
|
|
"default": "poll"
|
|
},
|
|
"pollInterval": {
|
|
"type": "string",
|
|
"description": "Human interval like '3x/day' or a cron expression",
|
|
"default": "3x/day"
|
|
},
|
|
"pollIntervalMin": {
|
|
"type": "number",
|
|
"minimum": 1,
|
|
"default": 5,
|
|
"description": "Poll interval in minutes controlling the nextSync computation"
|
|
},
|
|
"nextSync": {
|
|
"type": ["string", "null"],
|
|
"description": "Time after which cron may poll this mailbox again (lastSync + pollIntervalMin)"
|
|
},
|
|
"syncCursor": {
|
|
"type": "object",
|
|
"description": "High-watermark cursor per synchronised folder so a sync only fetches messages never stored before, instead of re-reading the N newest remote ids on every poll. IMAP keys are folder names and store {uidValidity, lastUid, lastRemoteNum}; POP3 uses the single key 'pop3' and stores {lastRemoteNum}. uidValidity guards against a remote mailbox being re-created: when the server value changes the cursor is discarded and the folder is fully re-scanned.",
|
|
"additionalProperties": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"uidValidity": { "type": ["number", "null"] },
|
|
"lastUid": { "type": ["number", "null"] },
|
|
"lastRemoteNum": { "type": ["number", "null"] },
|
|
"updatedAt": { "type": ["string", "null"] }
|
|
}
|
|
}
|
|
},
|
|
"syncing": {
|
|
"type": ["object", "null"],
|
|
"description": "Concurrency marker set while a synchronisation of this mailbox is running, so several users pressing sync at the same time cannot start concurrent provider syncs. Holds the alias that started it and the start date; null or absent when idle. A marker older than 10 minutes is treated as stale and ignored.",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"alias": { "type": "string" },
|
|
"since": { "type": "string" },
|
|
"remote": { "type": "boolean" }
|
|
}
|
|
},
|
|
"downloadMode": {
|
|
"type": "string",
|
|
"enum": ["lazy", "eager"],
|
|
"default": "lazy",
|
|
"description": "lazy: attachments fetched on-demand at first click; eager: fetched during sync (for auto-read/OCR workflows)"
|
|
},
|
|
"counts": {
|
|
"type": "object",
|
|
"properties": {
|
|
"total": { "type": "number", "description": "Mails stored in the tribe for this mailbox" },
|
|
"unread": { "type": "number", "description": "Mails with status 'new' for this mailbox" }
|
|
}
|
|
},
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["active", "paused", "error"],
|
|
"default": "active"
|
|
},
|
|
"lastSync": {
|
|
"type": ["string", "null"],
|
|
"description": "Last successful synchronisation timestamp"
|
|
},
|
|
"history": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
}
|
|
},
|
|
"availableTags": {
|
|
"type": "array",
|
|
"description": "Tags available for this mailbox, managed by druids. Each tag has a key (stored in mail.tags), label (display), and color (badge styling).",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"key": { "type": "string", "description": "Tag key stored in mail.tags" },
|
|
"label": { "type": "string", "description": "Display label" },
|
|
"color": { "type": "string", "enum": ["primary", "secondary", "accent", "success", "warning", "error", "info", "neutral"], "default": "primary", "description": "DaisyUI badge color" }
|
|
},
|
|
"required": ["key", "label"]
|
|
}
|
|
},
|
|
"apx3": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"agree": {
|
|
"type": "boolean",
|
|
"description": "APX3 payment agreement accepted at creation"
|
|
},
|
|
"volumePerWeek": {
|
|
"type": "number",
|
|
"minimum": 1,
|
|
"description": "Declared weekly storage & traffic volume in GB used for APX3 billing"
|
|
},
|
|
"dtAgree": {
|
|
"type": "string",
|
|
"description": "ISO date when the agreement was accepted"
|
|
}
|
|
}
|
|
},
|
|
"owner": {
|
|
"type": "string",
|
|
"description": "Alias who created the mailbox"
|
|
},
|
|
"dt_create": {
|
|
"type": "string"
|
|
},
|
|
"dt_update": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|