Commit Graph
2873 Commits
Author SHA1 Message Date
Matthew Meszaros bc73fc35a9 feat: give the unibox Compose button its visible label as the accessible name (screen-reader only on phones), hide the N key hint from assistive tech, and drop the drafts row's leftover top margin 2026-09-24 21:20:18 -07:00
Matthew Meszaros 74bf081d57 feat: move the unibox Compose button from the top of the folder rail into the conversation list title row (and the Scheduled view header) as a ghost sky button with an N key hint on every viewport, keeping compose drafts at the top of the rail, and update the marketing inbox mock and the unibox guide to match 2026-09-24 20:53:37 -07:00
Matthew Meszaros 46341f1a1d Merge pull request #684 from warmbly/fix/collapsed-rail-tooltips
feat: share one tooltip provider across the collapsed sidebar rail so tab names show after 120ms and instantly between rows, and pad the collapsed nav so the Inbox unread badge is no longer clipped at the top
2026-09-25 02:46:40 +00:00
Matthew Meszaros 85e63208a9 feat: share one tooltip provider across the collapsed sidebar rail so tab names show after 120ms and instantly between rows, and pad the collapsed nav so the Inbox unread badge is no longer clipped at the top 2026-09-24 19:43:47 -07:00
Matthew Meszaros cf83a13b6f Merge pull request #678 from warmbly/fix/vendor-authorizing-row-actions
feat: keep mailbox imports live and self-explaining, show vendor authorization progress with faster options, and finish sign-in rows through a later admin grant
v0.6.4
2026-09-24 17:15:19 +00:00
Matthew Meszaros 64627de271 feat: resume a sign-in row through a grant only when the grant lookup confirms it is usable on this instance, so a stored grant whose provider is no longer configured does not requeue its rows every minute 2026-09-24 19:10:02 +02:00
Matthew Meszaros f0861fa129 feat: make the backend drain wait for the import runner itself to stop on the shutdown deadline, resume only sign-in rows an active grant covers (decided in SQL so uncovered rows cannot crowd them out), wait for NATS consumers to close after stopping them, count rows a vendor is authorizing by provider on the import so the admin sign-in button counts and shows only Microsoft rows, keep failed and sign-in imports ahead of connecting ones in the imports menu, and base the pool banner's empty state and warming count on workspace totals only 2026-09-24 18:57:01 +02:00
Matthew Meszaros 755b6155c2 Merge pull request #679 from warmbly/fix/sent-count-and-reply-optout
feat: count only email steps in every sent total (contact drawer, Leads view and statuses, campaign progress, guardrails, org conduct, verification evidence, segments, admin, advisor), keep line breaks in synced body text and strip quoted history in any shape, classify delivery failures before out-of-office and tag them as bounces, record statusless failure notices from X-Failed-Recipients as permanent bounces, limit reply and inbox-tag opt-outs to people answering our outreach (never bounces, auto-replies or list mail), and recheck earlier reply opt-outs, lifting with an audit entry only those the message that wrote them no longer supports
2026-09-24 16:49:03 +00:00
Matthew Meszaros 256010725b feat: count only email steps in every sent total (contact drawer, Leads view and statuses, campaign progress, guardrails, org conduct, verification evidence, segments, admin, advisor), keep line breaks in synced body text and strip quoted history in any shape, classify delivery failures before out-of-office and tag them as bounces, record statusless failure notices from X-Failed-Recipients as permanent bounces, limit reply and inbox-tag opt-outs to people answering our outreach (never bounces, auto-replies or list mail), and recheck earlier reply opt-outs, lifting with an audit entry only those the message that wrote them no longer supports 2026-09-24 09:44:17 -07:00
Matthew Meszaros 561ba07b35 feat: send a deferred import progress event with the latest status and cancel it when a final one goes out, report a hidden import's real status instead of cancelled, rank failed and sign-in rows above authorizing ones in the imports menu and its badge, and count warming and connected mailboxes for the pool banner on the server (warming on the pool plan) rather than from the filtered, paged list 2026-09-24 18:38:47 +02:00
Matthew Meszaros d8e99877b2 feat: let an update finish work in flight instead of cutting it off, by having the import runner stop claiming on shutdown, hand back rows that never started without counting the claim and finish the rows it is connecting on an uncancelled context, the backend wait up to 45 seconds for those rows and for in-flight connects, the event bus finish the message being handled before it stops reading, and node units, the repository compose file and the installer's stack allow 60 seconds before a forced stop, with the grace period documented for Railway, Docker and Kubernetes 2026-09-24 18:31:06 +02:00
Matthew Meszaros ac663093c4 feat: label the faster options on a vendor authorization by what they do, Connect all at once (admin sign-in) for the whole domain and Sign in on a row for that mailbox only 2026-09-24 18:24:50 +02:00
Matthew Meszaros babf4bff67 feat: tell a person waiting on a vendor authorization that it can take up to an hour and offer the faster ways right there (Approve as a Microsoft 365 admin with the one-click admin consent, or Sign in on a row), and connect import rows still waiting for Google or Microsoft sign-in through an administrator's grant that now covers their domain within a minute instead of requiring the import to be run again 2026-09-24 18:20:20 +02:00
Matthew Meszaros 4930c578df feat: tell the person watching a vendor authorization what to do when it waits, naming the Google Admin domain-wide delegation step with Warmbly's client ID and scopes when the vendor waits on it, and saying when the vendor has not moved a request for 20 minutes with the time and the request id to give its support 2026-09-24 18:14:10 +02:00
Matthew Meszaros 06f4a270cc feat: keep the mailbox imports menu live and self-explaining (deferred rather than dropped progress events, a five-second refresh while an import runs, each import's state and what it waits on in words, a badge for imports that need you, and an × that hides an import for the workspace through POST /emails/imports/:id/dismiss with migration 000211, stopping a running one first), show the vendor's own status and the Microsoft and Google time expectations on rows being authorized, record a vendor row's mail host so it gets its provider icon and a working Sign in, drop the Fix button from rows the vendor is authorizing, and count warming mailboxes rather than connected ones in the pool banner, refreshed when mailboxes change 2026-09-24 17:46:46 +02:00
Matthew Meszaros c1f2f31322 Merge pull request #676 from warmbly/feat/warmup-inbox-placement
feat: record where every warmup email lands (inbox, Gmail tab, spam) per sender, day and recipient host in warmup_placement_daily, serve it from GET /analytics/warmup/placement, cap mailbox health at the measured 7-day inbox rate, and show it as an Inbox column, a mailbox Deliverability tab and a workspace placement section; replace every visible native checkbox in the dashboard with a themed Checkbox and make the mailbox drawer's tab bar scroll
v0.6.3
2026-09-24 12:54:18 +00:00
Matthew Meszaros e32b4f8893 feat: let a vertical wheel over a ScrollStrip at its edge scroll the page, name the seed section consistently in the deliverability guide, and keep the warmup placement live tests to their own receipts by dating the sweep fixture decades back and checking the live-counted flag directly 2026-09-24 05:48:26 -07:00
Matthew Meszaros b196b3c8be feat: count warmup placements exactly once through a consumer sweep that seeds history in batches instead of a locking migration backfill, add a concurrent unplaced-receipt index, publish WARMUP_PLACEMENT only when a receipt is counted, share one spam-flag list across warmup, placement tests and unibox folders, name ranked mailboxes from their own rows, default from to 30 days before to, keep ScrollStrip scrolling to itself, refresh account statuses at most every 5 minutes, and document rescued as requested 2026-09-24 05:28:51 -07:00
Matthew Meszaros b2d54fc873 feat: record where every warmup email lands (inbox, Gmail tab, spam) per sender, day and recipient host in warmup_placement_daily, serve it from GET /analytics/warmup/placement, cap mailbox health at the measured 7-day inbox rate, and show it as an Inbox column, a mailbox Deliverability tab and a workspace placement section; replace every visible native checkbox in the dashboard with a themed Checkbox and make the mailbox drawer's tab bar scroll 2026-09-24 05:28:51 -07:00
Matthew Meszaros 4a1bbe74d3 Merge pull request #677 from warmbly/fix/vendor-imported-mailbox-connection
feat: keep mailbox credential checks and imports from timing out behind a worker's command queue, and connect InboxKit mailboxes with no sign-in
2026-09-24 10:11:41 +00:00
Matthew Meszaros 7557d97866 feat: run a saved mailbox's placement, events, webhook and load on their own context so an expired caller deadline cannot skip them, bound bulk connects per row instead of per batch, have the worker reconciler remember the worker a load actually placed or moved a mailbox onto, keep an ADD_EMAIL that follows a REMOVE_EMAIL while the earlier load is still dialing by running it after that load, and show an import waiting only on vendor authorization as being authorized rather than importing 2026-09-24 11:58:49 +02:00
Matthew Meszaros 3eb3297b11 Merge remote-tracking branch 'origin/main' into fix/vendor-imported-mailbox-connection 2026-09-24 11:44:58 +02:00
Matthew Meszaros 549fb00be6 feat: keep mailbox credential checks and imports from timing out behind a worker's command queue by loading mailboxes off the bus loop (a republish never dials twice, commands wait for an in-flight load, a failed load raises the account's auth or server error), storing Kafka offsets for background commit instead of a synchronous commit per message, reconciling moved, unplaced and dead-worker mailboxes at once while spreading the safety-net republish over 30 minutes, sending checks over each worker's Redis channel with failover in placement order, retrying unanswered import rows within the lease, finishing a connect the browser left and an import row a restart interrupted, and connecting InboxKit Google and Microsoft mailboxes with no sign-in through a vendor-authorized grant that covers only the domains the vendor account lists 2026-09-24 11:44:58 +02:00
Matthew Meszaros 62fa2abf5f Merge pull request #675 from warmbly/fix/campaign-not-sending
feat: a campaign sends as soon as a lead is due when it starts, resumes or gets new leads, with pacing only between sends
2026-09-24 09:06:51 +00:00
Matthew Meszaros 79b583bcae feat: classify a campaign's parked wakeup itself as a sending tick's paced successor (IsPacedSuccessor: the preceding tick sent and completed within a minute of the park) so a reconciler re-seed or deferral recheck is pulled forward when leads arrive, skip cancelled ticks, and qualify the campaigns guide's first-send timing by mailbox window, cap and gap 2026-09-24 01:56:23 -07:00
Matthew Meszaros 87a346f4ff feat: wake a freshly seeded campaign chain (start, resume, schedule edit, reconciler re-seed) as soon as a lead is due instead of at the paced slot of the send after it, and let leads added to a waiting campaign pull its deferral recheck forward while leaving a sending tick's paced successor alone (scheduler.WakeSlot, CampaignRepository.LastTickSent) 2026-09-24 01:43:58 -07:00
Matthew Meszaros 13a0713090 Merge pull request #674 from warmbly/fix/unibox-forward-original-message
feat: unibox forward carries the original message under the note and signature via forward_message_id on POST /unibox/reply (#668)
v0.6.2
2026-09-24 04:54:26 +00:00
Matthew Meszaros ee70b7697a Merge remote-tracking branch 'origin/main' into fix/unibox-forward-original-message
# Conflicts:
#	docs/content/docs/api/reference/unibox.mdx
#	docs/content/docs/guides/unibox.mdx
#	docs/public/openapi.json
#	web/src/components/app/unibox/ReplyComposer.tsx
#	web/src/components/app/unibox/replyComposerDraft.test.tsx
2026-09-23 21:48:54 -07:00
Matthew Meszaros a5dfe169e4 Merge remote-tracking branch 'origin/main' into fix/unibox-forward-original-message 2026-09-23 21:38:59 -07:00
Matthew Meszaros bbd7942313 feat: unibox forward requires READ_UNIBOX alongside WRITE_UNIBOX, restores click tickets in a forwarded Warmbly send to their destinations, fills an empty-placeholder HTML note from its text, previews an empty-note forward in the Scheduled view, keeps a reply's leading blank lines, shares the stored-body read with GET /unibox/:id, and shows the Reply/Forward bar when a forward's message is no longer in the thread 2026-09-23 21:38:59 -07:00
Matthew Meszaros 408f1fea94 Merge pull request #671 from warmbly/feat/vendor-connect-fields
feat: connect inbox vendors with only an API key and pick mailboxes by workspace
2026-09-24 04:35:42 +00:00
Matthew Meszaros 462df7d025 Merge pull request #673 from warmbly/feat/unibox-reply-sender-picker
feat: let a Unibox reply or forward choose its sending mailbox, keep the provider thread only for the mailbox holding it, and scope scheduled sends to the organization (#670)
2026-09-24 04:34:30 +00:00
Matthew Meszaros a544847fcb feat: resolve a Unibox reply's Gmail thread per sending mailbox (its own copy of the conversation, or the thread its earlier reply started, and none for other providers or on a failed lookup keeps the handle), honour an API key's mailbox allowlist on scheduled list and cancel, fall back from a saved mailbox that is gone and block Send until the sender can send, fetch From candidates only when the picker opens, and fix the Unibox threading and drafts docs 2026-09-23 21:29:24 -07:00
Matthew Meszaros 6c4931c28a feat: unibox forward carries the original message, attached server-side from a new forward_message_id on POST /unibox/reply and stored on the queued task (migration 000208) so it goes out under the note and signature with its From, Date, Subject, To and Cc lines, sanitized HTML and text part; the composer allows an empty note and previews the forwarded message (#668) 2026-09-23 21:22:17 -07:00
Matthew Meszaros 13b0ff85c3 feat: refuse an InboxKit key that reaches no workspace with mailbox_vendor_no_workspace, and have the per-workspace credential lookup move on only past a mailbox a workspace does not hold, reporting any other vendor failure instead of a missing mailbox 2026-09-23 21:21:21 -07:00
Matthew Meszaros f9c24cdf88 Merge pull request #672 from warmbly/fix/step-performance-canvas-order
feat: order campaign Step performance by the canvas's step order and number rows as the canvas's Email N (#669)
2026-09-24 04:18:23 +00:00
Matthew Meszaros ce5eb4fd25 feat: let a Unibox reply or forward choose its sending mailbox in From (the shared MailboxPicker without Auto, kept in the draft and the undo-send), send the provider thread handle only from a mailbox that holds the thread so a switched reply threads on In-Reply-To alone, and scope scheduled sends, their cancel, count and cap to the organization whose mailboxes send them (#670) 2026-09-23 21:18:20 -07:00
Matthew Meszaros 39bb5567dc feat: order campaign Step performance by the canvas's step order (position, then created_at) instead of created_at, which the wizard writes identically for every step, number each row as its place among the email steps so it matches the canvas's Email N, label unnamed steps Email N in the dashboard, and document the steps order and position in the analytics API reference, guide and OpenAPI schema (#669) 2026-09-23 21:12:33 -07:00
Matthew Meszaros e35baa7f58 feat: connect every inbox vendor with only its API key by discovering the workspaces and organizations the key reaches (InboxKit, Zapmail, Infraforge, ScaledMail), carry the workspace in vendor mailbox and domain ids with a lookup for ids stored before, skip a workspace the key may not read, refuse a key that reaches none with mailbox_vendor_no_workspace, and add a workspace switcher to the mailbox picker that filters, counts picks and selects a whole workspace 2026-09-23 21:12:09 -07:00
Matthew Meszaros ad6e483b4f Merge pull request #667 from warmbly/fix/consumer-evict-deleted-mailbox
feat: evict a deleted mailbox from the fleet when a worker event's write is refused for it
v0.6.1
2026-09-23 17:35:34 +00:00
Matthew Meszaros 33b30272e0 feat: end a worker's new-arrival, folder-listing, sync-state, Gmail history and Graph delta event whose write is refused because its mailbox row is gone, confirmed against email_accounts rather than inferred from the foreign key, and evict that mailbox from every live worker instead of reporting the refusal or discarding it, so a worker still holding a deleted mailbox is told to stop on its next relay 2026-09-23 19:17:10 +02:00
Matthew Meszaros ec97fede97 Merge pull request #666 from warmbly/fix/advisor-no-senders-copy
feat: word the advisor's no-senders finding by how the campaign picks mailboxes (every active mailbox, picked by hand, by tag, or both), carrying picked and tag counts in the snapshot and a sender_selection evidence field in place of sender_strategy so the narration never points an all-mailboxes campaign at its tags (#661)
v0.6.0
2026-09-23 16:28:39 +00:00
Matthew Meszaros 39318b9217 feat: name the advisor no-senders evidence counts picked_mailbox_count and tag_count so the narration reads them as counts rather than tag names 2026-09-23 09:22:56 -07:00
Matthew Meszaros 224a0dfa1f feat: word the advisor's no-senders finding by how the campaign picks mailboxes (every active mailbox, picked by hand, by tag, or both), carrying picked and tag counts in the snapshot and a sender_selection evidence field in place of sender_strategy so the narration never points an all-mailboxes campaign at its tags (#661) 2026-09-23 09:16:28 -07:00
Matthew Meszaros c40eeb1978 Merge pull request #665 from warmbly/fix/campaign-sender-resolution
feat: count the all-active-mailboxes fallback in the advisor's campaign sender count, re-run the advisor when a campaign's senders, tags or status change, start a new lead from a mailbox whose min gap (warmup included) has elapsed instead of deferring the campaign, and scope the pre-start mailbox check to the organization
2026-09-23 16:10:17 +00:00
Matthew Meszaros ed19181846 Merge pull request #664 from warmbly/feature/mailbox-csv-import-mapping
feat: mailbox import with column mapping and detection, whole-domain Google Workspace and Microsoft 365 connects, inbox vendor imports, sending domains page, and retirement of per-mailbox Google sign-in
2026-09-23 16:09:56 +00:00
Matthew Meszaros 145e9c45d7 feat: refresh the advisor on a status-only campaign PATCH, fall back to the whole pool under ESP prefer when no matching mailbox is past its min gap, and draw each candidate's behaviour gap once so the selection filter and the send enforce the same gap 2026-09-23 09:06:28 -07:00
Matthew Meszaros 0eb4e30fec feat: record a Microsoft 365 grant only when the consenting sign-in holds the Global Administrator or Privileged Role Administrator role, validate a tracking host before any vendor DNS write, clear Graph delta cursors when an Outlook mailbox moves onto a grant, keep a switched-off mailbox off when it moves unless its sign-in stopped it, treat pool-link mailboxes as managed, park a delegated mailbox without a grant as inactive, honour MAILVENDOR_SANDBOX_URL only when APP_ENV is dev, drop a vendor's cached domains with its key, retry a failed import redirect setup, keep address:password pastes whose password has a comma, and move the vendor import components to import/vendors so the Go vendor ignore rule no longer drops them 2026-09-23 09:03:25 -07:00
Matthew Meszaros d474fdc4b2 feat: count the all-active-mailboxes fallback in the advisor's campaign sender count, re-run the advisor when a campaign's senders, tags or status change, start a new lead from a mailbox whose min gap (warmup included) has elapsed instead of deferring the campaign, and scope the pre-start mailbox check to the organization 2026-09-23 08:43:06 -07:00
Matthew Meszaros e58921484d feat: rebuild mailbox import around column mapping and automatic host and sign-in detection (CSV, XLSX, pasted lists, saved mappings, retryable rows with fixes, migrations 000205-000206), connect whole Google Workspace domains and Microsoft 365 organizations through a proved administrator grant, import from inbox vendors (InboxKit, Zapmail, Mailforge, Infraforge, Maildoso, Cheap Inboxes, ScaledMail) with vendor-managed forwarding and DNS, add a sending domains page with per-domain tracking and verified root redirects, unify Add account into one Google and one Microsoft entry with per-method choices, mark per-mailbox Google sign-in as retiring with in-place moves to the admin grant or an app password, allow the loopback security mode in the credential columns (migration 000207), read semicolon-separated CSVs, and add a mock vendor API to the sandbox 2026-09-23 08:41:01 -07:00