Retry the shared-library build, which the LAN uplink keeps corrupting
Three builds died today on "Tag mismatch" pulling a jar — and the mirror added an hour ago did not help, because kbservice, mcpgatewayservice and ragservice hit...
Mirror Maven Central through the Google GCS copy
Every Docker stage starts from a cold ~/.m2 and refetches the whole dependency tree, so Central sees the full weight of every concurrent service build. It answe...
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...
Restore the files 2b23346 dropped, and answer an oversized send with 413
2b23346 was committed through a private index that was never seeded from HEAD, so its tree held only the three files staged into it and the commit deleted the o...
Stop capping every send at 1MB, so a pasted image can actually go out
Composing with a pasted image failed with a bare "Failed to send email". The composer inlines the paste into the body HTML as a base64 data URI, which rides in ...
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 ...
Stop Hibernate mangling the "::" casts in the native SQL
Hibernate's native-query parser treats "::" as an escaped colon and forwards a single ":". CockroachDB received **************** ARRAY[]:text[]), ' ') and r...
Keep retrying the indexer's durable NATS consumer after a deploy
A rolling deploy overlaps pods and the outgoing one still holds the durable consumer, so the incoming pod's bind to "email-metadata-indexer" fails with [SUB-900...
Adapt the metadata indexers to array-typed columns
Follows the kamo-shared-library change that maps conversations/search_index array columns as String[]/UUID[] rather than List<T>, which is what stopped every in...
Bound the bulk folder index and stop it on structural failure
Uncommitted work from a concurrent session, swept in so the tree is clean. The bulk index walked pages with totalPages set to Integer.MAX_VALUE and no ceiling,...
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...
Never match a lead against the company's own addresses
A lead whose e-mail was set to noreply@kamocrm.com matched every message that address had ever sent — one lead record surfaced the company's entire outbound mai...
Page the lead sweep until the window is covered
A single fixed page silently lost mail whenever a mailbox took more than pageSize messages between ticks — a newsletter burst, a busy shared inbox, or just the ...
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 ...
Address replies at Reply-To, and stop leaking SMTP exceptions to the UI
A quick reply to a KamoCRM notification failed with `{"error":"Invalid Addresses"}` rendered verbatim in the reply box. That string is Jakarta Mail's own wordin...
Stop classifying a multipart/related HTML root as an attachment
Every transactional email we send with an inlined org logo arrived in our own /messages viewer with a correct subject and a completely empty body. isAttachment...
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 ...
Scan the shared MFA repositories
MfaEnrollmentService is a @Service in kamo-shared-library, so the wildcard @ComponentScan("com.kamo") in this application constructs it whether or not this serv...
Merge duplicate kamo key that crashlooped EmailService
The new EmailService pod has been in CrashLoopBackOff since 16e8a05 — 22 restarts, never once started. snakeyaml raises DuplicateKeyException on a repeated top-...
Commit outstanding work in progress
Staged and committed as-is so nothing is left uncommitted in the working tree. 1 file changed, 12 insertions(+)
Harden the kubectl download against flaky egress [skip ci]
dl.k8s.io over the runner's egress intermittently drops mid-transfer: curl: (56) OpenSSL SSL_read: decryption failed or bad record mac which fails the deploy ...
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...
Add missing CampaignController REST endpoints for /api/email/campaigns
The bulk-email workspace/editor call GET/POST /api/email/campaigns etc., but only CampaignService (the @Service) was ever created — no @RestController exposed i...
Remove ambiguous unsubscribe requestMatcher that crashed startup
EmailService mounts two servlets (MVC DispatcherServlet + Spring-WS MessageDispatcherServlet at /services/*), so a bare string requestMatchers( "/api/email/unsu...
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: - ...
Rebuild to pick up **************** canonical keys
No source change. EmailService bundles kamo-shared-library at build time, so the CANONICAL_KEYS fix (shared-lib c028131) only reaches its runtime self-heal afte...
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...
Stop serializing computed xoauth2 getter that broke MailCredentials Redis cache
MailCredentials is cached in Redis (GenericJackson2Json). The added `isXoauth2()` boolean getter was serialized as a "xoauth2" property but has no field to read...
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...
Scope KamoMail mailbox/domain listing to the org's own domains (cross-tenant leak)
SECURITY: **************** ran 'SELECT email FROM virtual_users' (and **************** 'SELECT name FROM virtual_domains') with no org scoping, so mailbox/domai...
Persist selected OAuth provider on callback so it stops reverting to KamoMail
Switching an org to Microsoft 365 (or Google Workspace / Zoho) never stuck: the OAuth callback stored tokens and only flipped status on a pre-existing provider ...
Resolve welcome-email logo from the org theme host, not the apex
Header/footer logos in system emails (welcome/verification) were built as **************** — an apex path that only exists on the Kamo marketing site, so for cu...
Constant-time internal-auth secret compare (timing oracle)
Replace String.equals with MessageDigest.isEqual so response latency cannot leak the X-Internal-Auth shared secret byte-by-byte. Fleet-wide sweep of the copy-pa...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.