Matthew Meszaros
90f3f57eb9
feat: keep automated notifications that need the recipient's action (failed payment, suspended account, suspicious sign-in, sending limit, expiring service) in the inbox with an Action required label, view and mail-that-needs-action notification, let workspace tagging questions also run on automated notifications, add warmblyctl inbox-tag backfill --recheck-notifications, and document it
2026-09-26 21:28:06 -07:00
Matthew Meszaros
d95a1075de
Merge pull request #699 from warmbly/feature/contact-email-provider
...
feat: detect each contact's inbox provider from its domain's MX and SPF, show, sort and filter it across contact lists and segments, and use it for campaign ESP matching
2026-09-26 13:52:02 +00:00
Matthew Meszaros
2c156ec07e
feat: hold the contact provider sweep lease by owner token with a compare-and-delete and end each run before it can expire, recognise Microsoft 365 tenant onmicrosoft.com domains for ESP matching, count checked domains with no known provider with other rather than undetected, and report an unknown-provider filter when saving it as a segment
2026-09-26 06:47:29 -07:00
Matthew Meszaros
8812cba439
feat: detect each contact's inbox provider from its domain's MX and SPF in a backend sweep, show it as a sortable Email provider column with the provider logo, filter and segment on it across contacts, campaign leads and segments, and use it for campaign ESP matching including Workspace and Microsoft 365 custom domains and the coverage panel's per-provider lead counts
2026-09-26 06:33:44 -07:00
Matthew Meszaros
014ba06b3a
feat: weight warmup partners by the sender's verified spam rate per recipient mail host instead of per address domain, report deliverability warmup placement and the placement_in_spam webhook by mail host, mark IMAP warmup mail not-junk before it leaves Junk, send single-part text mail over SMTP with a fixed header order, and update the warmup, deliverability, analytics, webhook and OpenAPI docs
2026-09-26 06:30:22 -07:00
Matthew Meszaros
c6027fecde
Merge pull request #694 from warmbly/fix/premium-warmup-pool-partners
...
feat: borrow the best proven free warmup mailboxes whenever a premium mailbox has too few outside-workspace partners, reserve a quarter of every inbox's daily warmup capacity for premium senders, and show the pool and partner cap in the mailbox drawer
2026-09-26 05:07:38 +00:00
Matthew Meszaros
af8b08d27a
feat: rank borrowed free warmup mailboxes strictly by provider then tenure then activity, build the two inbound-share candidate suffixes once, and correct the partner-limit wording in the drawer, OpenAPI, warmup and Warmbly Cloud docs and AGENTS.md
2026-09-25 21:52:45 -07:00
Matthew Meszaros
6e62c500c3
feat: borrow the best proven free warmup mailboxes whenever a premium mailbox has fewer outside-workspace partners than max(25, its warmup ceiling) so siblings no longer block borrowing, keep a quarter of every inbox's daily warmup capacity for premium senders, and show the pool and any partner cap on today's target in the mailbox drawer
2026-09-25 21:47:36 -07:00
Matthew Meszaros
caf1852217
feat: keep placement seeds out of warmup pools as recipients too, store a probe's Message-ID before the send, hold queued probes against the sender's day and size a test to what is left, claim due monitors so one replica runs each, write comparison halves in one transaction, scan each seed's mail once per tick, keep test history when a mailbox is deleted, default to 20 seeds a minute apart, and render cloud-panel tests without a real lead by default
2026-09-25 21:46:09 -07:00
Matthew Meszaros
989daede3c
feat: add the Placement tests dashboard with the test list, detail and comparison views, New test dialog, Seed inboxes tab, campaign step Test inbox placement action and Placement monitor card, live updates over PLACEMENT_TEST_UPDATED with a slow poll only while the socket is down, the two placement notification categories, and seed-aware warmup errors on Mailboxes
2026-09-25 21:03:26 -07:00
Matthew Meszaros
d6e4c42e50
feat: give each domain in a bulk sending-domain setup a 20s deadline and send 25 per request so every batch answers inside the dashboard timeout, send each domain's resolved tracking host and website from the bulk dialog so a kept verified host is not replaced by the base subdomain, and release the CSV export's blob URL after the download starts
2026-09-25 09:44:00 -07:00
Matthew Meszaros
356c215d37
feat: limit Check DNS now on Sending domains to tracking hosts still waiting for DNS so a verified host covering part of a domain is never extended to its other mailboxes
2026-09-25 09:32:05 -07:00
Matthew Meszaros
6b9df08f3e
Merge remote-tracking branch 'origin/main' into feature/domain-bulk-setup
2026-09-25 09:30:36 -07:00
Matthew Meszaros
0fedc7abe6
feat: default tracking hosts to link.<domain>, set one tracking subdomain and redirect website for every domain in mailbox imports and on Sending domains with a per-domain dropdown to override each, add POST /emails/domains/bulk that goes through the inbox vendor's API where it can, add multi-select with check DNS, copy records, CSV export, clear tracking and remove redirect to Sending domains, and fix the sandbox seed's deliverability conflict target
2026-09-25 09:30:36 -07:00
Matthew Meszaros
c93bf1fcca
Merge remote-tracking branch 'origin/main' into feat/compose-placement
...
# Conflicts:
# web/src/components/app/unibox/ConversationList.tsx
2026-09-24 21:20:31 -07:00
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
e5e559f5fb
Merge pull request #688 from warmbly/feature/unibox-rail-lead-pause
...
feat: pause and resume a lead from the unibox contact panel and the reply composer (#681 )
2026-09-25 03:53:22 +00:00
Matthew Meszaros
d9fd7df42b
Merge remote-tracking branch 'origin/main' into feature/unibox-rail-lead-pause
...
# Conflicts:
# web/src/components/app/contacts/ContactEdit.tsx
2026-09-24 20:39:58 -07:00
Matthew Meszaros
78a742e9f3
Merge pull request #689 from warmbly/fix/inbox-bulk-archive-reappearing
...
feat: animate unibox rows out in the direction of the action (archive, trash, back to inbox, snooze) with a labelled underlay and in with a fade or grow, keep the list mounted so bulk exits play and give re-entering keys a fresh presence key so a refilling list never strands archived rows, fade new pages in at full height so infinite scroll stops chaining every page, batch bulk archive/read/snooze requests under the 500-id cap, show an all-caught-up state and an animated selection bar, and page the conversation list from the last returned row so no conversation is skipped at a page boundary
2026-09-25 03:36:49 +00:00
Matthew Meszaros
21991ccc6b
Merge pull request #686 from warmbly/feature/contact-custom-field-inputs
...
feat: custom field inputs when adding or editing a contact
2026-09-25 03:27:34 +00:00
Matthew Meszaros
9b310cf0c5
feat: rebase contact custom fields key by key so a teammate's new field is kept instead of saved as a removal, lock stored field names the server refuses and check every key a save sends, keep saved fields visible across tab switches, give new-field rows stable ids, and stop Enter in a field name from submitting the New contact form
2026-09-24 20:25:25 -07:00
Matthew Meszaros
5e49d16e5d
feat: animate unibox rows out in the direction of the action (archive, trash, back to inbox, snooze) with a labelled underlay and in with a fade or grow, keep the list mounted so bulk exits play and give re-entering keys a fresh presence key so a refilling list never strands archived rows, fade new pages in at full height so infinite scroll stops chaining every page, batch bulk archive/read/snooze requests under the 500-id cap, show an all-caught-up state and an animated selection bar, and page the conversation list from the last returned row so no conversation is skipped at a page boundary
2026-09-24 20:24:31 -07:00
Matthew Meszaros
ed18fad2cd
feat: pause nothing from the reply composer when the lead's state cannot be re-read, keep an armed follow-up pause pointed at at least one campaign and clear it after the send, report already-held campaigns apart from ones that could not be paused, word a paused or blocked next step by its reason in the unibox contact panel, and keep Stop disabled while Resume is in flight
2026-09-24 20:20:49 -07:00
Matthew Meszaros
77f0c56e72
Merge pull request #687 from warmbly/feature/automated-mail-routing-and-labels
...
feat: keep automated mail out of the inbox and rename automatic labels to plain words
2026-09-25 03:19:29 +00:00
Matthew Meszaros
fe7f416a1e
feat: pause and resume a lead from the unibox contact panel, which now lists each campaign with the lead's status and next step or hold, add a Pause follow-ups option to the reply composer that holds the recipient's ticked campaigns once the reply is accepted (counted from a scheduled reply's send time), add Pause lead to the contact Activity tab's campaign cards, end a lead's flow on the router's exclusion and let it decide whether a reply ended it, and stop per-contact send events refetching every other contact's campaign-state preview (issue #681 )
2026-09-24 20:13:56 -07:00
Matthew Meszaros
9dee88bcb2
feat: keep conversations the inbox tagger judges automated (security alerts, verification codes, notifications, bounces, auto-replies) out of Inbox, Unread, mailbox and tag views and the unread badge and list them in the Automated view via a new unibox automated filter and overview counts, map no-reply header verdicts to Notification, and rename the automatic labels to plain words (Interested, Meeting, Needs reply, Follow up, Gone quiet and more) with a migration that renames, merges and prunes the old ones
2026-09-24 20:08:45 -07:00
Matthew Meszaros
720faf3acd
feat: show every workspace custom field as its own input in the New contact dialog and the contact Details tab (collapsed after six, filterable past twelve), suggest existing fields while naming a new one or a bulk-edit key with Use it for near-matches, validate names and duplicates before saving, and send removed or cleared fields as empty so the merge-on-update endpoint actually drops them
2026-09-24 20:01:21 -07:00
Matthew Meszaros
a54e9a3a2f
feat: keep a campaign's pass chain running through every failure (a pass whose hand-off to a worker fails or that errors is followed by another a minute later instead of waiting on the reconciler, retries move their slot, dead-lettered passes replay through the campaign lock), pass over mailboxes no heartbeating worker holds (worker_id now loaded with the sender pool, shown as Reconnecting in the send plan), count a hand-off failure against the lead only when it is the lead's, and try up to 200 due leads per pass with a daily activity line when all are waiting
2026-09-24 19:56:14 -07: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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Matthew Meszaros
331aeb4db3
Merge origin/main into feature/open-tracking-device-client
2026-09-23 02:06:04 -07:00