Skip to content
KAMOUniverse

Changelog

What's new.

Every improvement to the platform, as it ships.

  1. · EmailService

    IMAP/SMTP-backed send, folder, and search for cloud stubs

    Extract the IMAP/SMTP delegation pattern into AbstractImapBackedCloudProvider and have Zoho, IceWarp, Exchange, Google Workspace, and Microsoft 365 extend it. The base class implements MailSender, MailReader, FolderManager, and SearchProvider on top of EmailImapService, EmailSmtpService, and SearchService — the same services KamoMail uses — so: - send / saveDraft work for any cloud provider with SMTP credentials. - All folder operations (create / rename / delete / move / setFlags / deleteMessage) work via IMAP. - Search delegates to the existing SearchService. - Read operations and inline cid: rendering continue to flow through the shared EmailImapService parser. The remaining stubs in each concrete provider — RealtimeNotifier (where applicable), DomainManager, and MailboxProvisioner — genuinely need provider-native admin APIs (Microsoft Graph, Google Admin SDK, Zoho Admin API, EWS, IceWarp admin) that aren't wired into this codebase yet. Each stub now carries a TODO-style comment naming the API that would implement it.

  2. · EmailService

    IMAP-backed MailReader for the cloud-provider stubs

    Zoho, IceWarp, Exchange, Google Workspace, and Microsoft 365 all expose IMAP, so wire each cloud-provider stub's MailReader methods through EmailImapService instead of throwing UnsupportedOperationException. This: - Unblocks reading messages on those providers when only IMAP credentials are configured (the most common deployment today). - Makes the new contentId/inline attachment metadata flow uniformly across every provider, since EmailImapService is the single parser. - Lets the inline-image endpoint resolve cid: references for any provider. The remaining cloud-provider methods (sending, folder management, provisioning, domain ops) are still UnsupportedOperationException — those need provider-native APIs and aren't in scope here. Also adds MailContext.toMailCredentials() so providers (and the existing KamoMailReader adapter) share a single credentials-conversion helper.

  3. · kamo-internal

    Render inline cid: images via the new EmailService endpoint

    When a message exposes inline parts (each carrying a contentId), the email renderer now rewrites <img src="cid:..."> references at mount time to **************** which the proxy now also forwards Cache-Control on so the browser caches the fetched image. - EmailAttachment (both in conversationTypes and the local copy in MessageBrowser) gains contentId and inline fields. - SanitizedEmailRenderer accepts inlineImageBaseUrl + inlineContentIds; on cid: imgs it rewrites known cids and hides the rest, with the existing onerror handler still hiding any other broken image. - The dedicated cid stripping that lived in the sanitizer is reverted — rewriting belongs at render time, where the message context exists. - The visible attachments list in ThreadDetailView and MessageBrowser filters out inline parts so embedded signature logos no longer appear as downloadable attachments.

  4. · EmailService

    Serve inline image MIME parts and surface Content-ID metadata

    Render <img src="cid:..."> in the messages UI by exposing the inline parts that the HTML body references. - AttachmentInfo gains contentId (without angle brackets) and inline flag. - parseMultipart and getAttachment share a single isAttachmentPart predicate and a recursive walker, so inline parts nested inside multipart/related are captured (and their indices stay aligned across the two methods). Previously the recursion overwrote the parent's attachments list, which also dropped real attachments in nested structures. - hasAttachment is now driven by non-inline parts only — signature logos no longer light up the paperclip on every message. - New endpoint GET **************** on both EmailController and SharedMailboxMailController; resolves cid via the parsed AttachmentInfo, streams the part with Content-Disposition: inline and Cache-Control: private, max-age=3600.

  5. · KlusterServices

    Add pricing@kamocrm.com mailbox and external IMAP NodePort

    - New Service mail/dovecot-imap-external (NodePort 30143 -> 143) so IMAP can be reached from outside the cluster on $NODE:30143. - Seed pricing@kamocrm.com in mysql-init so a fresh DB bootstrap recreates the mailbox; the live row is already present in MySQL.

  6. · kamo-internal

    Redesign ChatsList rows — elegant layout, no horizontal scroll, online dots, unread badge, relative timestamps

  7. · MediaService

    Add GET /sessions/{guid}/members endpoint with display-name priority

    Returns member list with name resolved via usernameAlias → fullName → alias → username, matching the same priority as the chat sessions list. This feeds ChatBox.loadMembers() so the tool window title bar can show the correct preferred name.

  8. · kamo-internal

    Derive and dispatch tool window title from session members

    Adds onMembersChange callback to ChatBox; ChatTool derives the title (single name for 1-on-1, or '<name> (+N more)' for groups) and dispatches tool:title to update the ToolWindowShell title bar dynamically.

  9. · kamo-internal

    Lift search above tab strip, share query across Members and Chats tabs

    Moves the search TextField from MemberList into NavTopPanel above the Tabs. Passes searchQuery as a prop to both MemberList and ChatsList so a single field filters both tabs. ChatsList filters rows by matching any non-self member's name.

  10. · MediaService

    Augment unread broadcast with ACTIVITY payload for chats-list updates

  11. · kamo-internal

    Live chats-list updates via NATS unread channel

  12. · kamo-internal

    Tabs for members/chats in interaction center panel

  13. · kamo-internal

    Chats list with infinite scroll, virtualized via IntersectionObserver

  14. · kamo-internal

    Multi-select in MemberList for starting group chats

  15. · kamo-internal

    Chat header with avatar stack, title popover, and member picker

  16. · kamo-internal

    Composer with drag-drop, pending attachment chips, multi-line input

  17. · kamo-internal

    Message bubble with avatars, hover actions, and seen indicator

  18. · kamo-internal

    Inline attachment rendering and lightbox

  19. · kamo-internal

    Client types and hooks for sessions, receipts, attachments

  20. · kamo-internal

    Proxy routes for find-or-create, members, attachments, imaging proxy, mute, revoke

    Extract shared **************** helper to app/lib/mediaServiceUrl.ts. Add proxy routes: find-or-create, members, receipts, attachments (streaming), mutes, revoke,

  21. · MediaService

    Configmap entries for attachment limits and multipart

  22. · MediaService

    Paged chat list with previews, members, unread counts

    that returns ChatListRowDto rows including last message preview, member summaries, per-session unread counts, and ownLastViewedAt.

  23. · kamo-shared-library

    Add countUnreadAfter(guid, memberId, since) to MediaObjRepository

    Needed by paged chat-list endpoint to compute per-session unread counts when ownLastViewedAt is a LocalDateTime pointer rather than a message UUID.

  24. · MediaService

    Real NATS publisher impl and READ_RECEIPT broadcast

  25. · MediaService

    Per-viewer mute endpoint and message filter

  26. · kamo-shared-library

    Add **************** to MediaSessionMuteRepository

  27. · MediaService

    Imaging proxy with HTTP Range support and per-member download tracking

  28. · kamo-shared-library

    Add MediaObjImgDownloadRepository with existsByObjImgIdAndMemberId

    Required by ImagingProxyService (Task 10) to deduplicate per-member download tracking without a full table scan.

  29. · kamo-shared-library

    Add CHAT_ATTACHMENT assoc type with imaging-chat-attachments bucket

  30. · kamo-shared-library

    Service methods for exact-match find/create, member add, mute, revoke, read

Your universe is waiting.

Start free in minutes. Add products whenever you are ready — no migration, no new logins.

Free forever — no credit card required