A member is only told about apps they have
A notification kind belongs to an app — a lead callback is Leads, a meeting reminder is Meetings — but raise() asked only whether the member had muted it. So a ...
Preview variables for the bug-status-changed template
The admin preview renders a template against a sample variable map, and this one has no arm — so an org administrator opening SYSTEM_BUG_STATUS_CHANGED would se...
Persist the two company phone toggles
Reads and writes userCompanyPhoneMain / userCompanyPhoneTollFree on the signature field config, so the Content tab's new switches survive a save. saveFieldConf...
Back the personal-mailbox API the console already calls
Eighteen client methods over twelve routes that had been shipping with no backend behind them. A member reaches only their own inbox and configures it only once...
Serve Google's OAuth callback on /api/email/oauth/callback
The platform console needs an address to show an operator setting up the Google Workspace registration, the way VOIP has /api/voip/oauth/callback. The only emai...
Serve the home-page unread digest from the index, never from IMAP
A widget on the home page is on screen for everyone all day, whether or not anybody is reading mail — and a member's IMAP connections are a shared budget of ten...
Serve and announce the home-page calendar widgets
CalendarWidgetService answers what a widget actually needs and the calendar page hasEarlier/hasLater so an arrow greys out instead of offering an empty page. Th...
Scan the org's mailboxes for a lead's past e-mail on request
Serves the "Associate Past E-Mails w/ Lead" tick-box. Given a lead and the address just recorded on it, read INBOX and Sent of every mailbox in that lead's orga...
Publish every change of state, not only arrivals
A member has this open in more than one tab about as often as not, and often on a phone as well. Each of those holds its own socket and draws its own bell, and ...
A paged, filterable history
The centre could answer one question: the most recent hundred, unread or not, with no way to ask for what had already been read. So anything a member had seen w...
Read one event by id
The lead page holds a callback's event id and wants to reopen it in the same dialog the calendar uses, so it needs to be able to fetch the event on its own. Sc...
One integer for the mail badge, and count what the index path is worth
Three things, all about knowing rather than assuming. The nav-top unread badge fetched the entire folder tree and picked INBOX out of the result — the most exp...
Prove a folder unchanged with HIGHESTMODSEQ, then serve it from the index
Turns the index-backed message list on, by fixing the thing that made it unsafe rather than by flipping the flag. The old check compared message counts and UID...
Serve a folder listing from the index when it can prove it is current
The rows behind a message list are already in Postgres — the metadata index holds sender, subject, date, size, attachment and flags for every message it has see...
Size each mailbox against the organization's storage
Dovecot now enforces a per-mailbox limit, and nothing was setting the column it reads. This writes it nightly, after the storage snapshot so the capacity being ...
Manage an event's guest list
The dialog could show who was already on an event but never add or remove anyone; the only guest operation was re-notifying people who were somehow already ther...
Let the conflicts endpoint exclude the event being edited
ConflictDetectionService has always taken an excludeEventId; this endpoint passed null. Without it an event overlaps itself, so the moment the event dialog star...
Sync the organisation calendar to phones, without opening a hole
The shared calendar has no owner, so the account-scoped DAV listing could never return it: company events were plainly there on the web and invisible on every p...
Point at YugabyteDB and use PostgreSQLDialect
CockroachDB has been replaced by YugabyteDB. Connection strings move from cockroachdb-public:26257 to yb-tserver-service:5433, and the Hibernate dialect from **...
Persist and serve the whole contact, not just its name
The REST layer serialised the JPA entities directly. A Contact has no mapping to its emails, phones, addresses, organisations, URLs, IMs or relationships — thos...
Measure each org's own KamoMail mailboxes
Walks every mailbox Kamo hosts and records, per arrival day, the RFC822 bytes it holds — headers, body and encoded attachments, across every folder including Tr...
Let /sendable drop the alias group for callers that open mailboxes
The /messages mailbox switcher offers the same set as the composer's From field, minus one thing: an alias cannot be opened. Mail addressed to it lands in the m...
Preview variables for the e-signature templates
The admin template editor renders every placeholder blank for a key with no sampleVariables arm, so the seven esign templates previewed as a page of empty gaps ...
Searchable, paged endpoint for the addresses a member can send from
GET /api/email/mailboxes/sendable answers the same question as /accessible — every address the member may send as — but as one merged stream that is searched an...
Name a primary mailbox after the member who holds it
A mailbox someone holds as their primary is that person's address, so presenting it under whatever the mailbox was labelled at provisioning time — "Sales Desk" ...
Act on a whole folder, not just the page you scrolled
Mark all read and Empty folder are folder-wide operations the client cannot express by batching uids: it only ever holds the page it has scrolled, so a folder w...
Publish mailbox-change events so the mail views stop polling
The folder tree, conversation list and message list each ran their own 30-second timer, reloading on the chance that something had moved. The WebSocket already ...
Push INBOX unread counts over NATS/WebSocket instead of polling
The nav-top mail badge in kamo-internal refreshed itself by calling /api/email/folders every 30 seconds, per browser tab. That endpoint walks the entire folder ...
Resolve the people behind the addresses on a message
A message header knows an address and whatever display name the sender chose to put beside it. The organization already knows far more — colleagues, address boo...
Associate lead correspondence, and fix the dead push indexer
Adds the mail half of the lead Communications tab, plus the ingestion it needed to exist at all. The platform has no working mail push: IMAP IDLE is hardcoded ...
Preview samples for the nine opportunity notifications
Without an arm here the admin Email Templates editor renders every placeholder blank, so anyone customising these nine would be editing an empty skeleton. One ...
Preview variables for PHI_ACCESS_ALERT
Without a sampleVariables arm the admin Email Templates preview renders every placeholder blank, so whoever is asked to approve the wording of a security alert ...
Avatar endpoints; fix unauthenticated reachability and contact tenancy
Adds the mailbox side of sender avatars, and fixes three pre-existing holes this work would otherwise have built on top of. AUTHENTICATION. OTKPreAuthFilter us...
Bulk email campaign backend — provider, dispatcher, compliance, realtime
Backend for org-level bulk email campaigns, entirely separate from the everyday email provider so it can't be throttled/blocklisted alongside business mail: - ...
Sample variables for the LEADS_ASSIGNED template
Without a case here the admin template editor's Preview renders the new template with every placeholder blank, which reads as a broken template rather than an u...
Accept X-***-Token for mobile clients in OTKPreAuthFilter
per-tab session id as X-***-Token (matching **************** When present (and no X-OTK), resolve the session non-consumingly and set the same request attribute...
Support "unblock forever" remote-image consent
Adds a wildcard consent (allowAll / isAlwaysAllowed) so a member can opt to display external images in every message. Reuses the existing consent table via a re...
Inline-CID org logo (SVG->PNG) so it renders in Gmail; remove message content; preserve From-domain case
- FIX (security): notification emails carry no message body — remove messagePreview from template vars, ledger, samples and the settings toggle. - FIX (logo):...
Editor sample variables for missed-message notification templates
Preview samples for MISSED_CHAT_MESSAGE and SUPPORT_TICKET_REPLY incl. raw vs html-escaped sender/title variants used by the canonical bodies.
Microsoft 365 mail via Microsoft Graph app-only (zero per-mailbox setup)
Microsoft 365 mail now reads/sends through Microsoft Graph app-only (Mail.ReadWrite/Mail.Send application permissions) instead of IMAP — one app credential cove...
Route all cloud providers' mail through IMAP/SMTP with OAuth2 (XOAUTH2)
Cloud providers (Microsoft 365, Exchange Online, Google Workspace, Zoho, IceWarp) inherited read/send from **************** but the resolver never populated IMA...
Server-side "display external images" consent
Replaces the client-local (localStorage) remembering of the external-image choice with a durable per-member record. New RemoteImageConsentService (fail-soft rea...
Sample vars for meeting-summary template preview
Adds a sampleVariables case for the new meeting-summary template so the steward preview UI renders realistic content.
Internal endpoint to create/cancel a member's calendar event
POST /api/internal/calendar/events (X-Internal-Auth gated) resolves member -> user -> primary calendar (creating a default if needed) and creates an event. Used...
Fixed public redirect + gateway-forwarded callback
Platform email OAuth (Microsoft 365 / Google / Zoho) had no valid public redirect URI: the redirect was derived from the request host, which in prod is the clus...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
