Commit Graph
2834 Commits
Author SHA1 Message Date
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
Matthew Meszaros 531b5d66fa Merge pull request #663 from warmbly/fix/notification-system
feat: keep warmup out of Unibox notifications and the unread badge, and tie reply notifications to their message (#659)
2026-09-23 14:51:50 +00:00
Matthew Meszaros df62ba70a1 feat: write a message notification read with no email when its message is already read (locked against a concurrent read), cancel an email-only notification's pending email when its message is read, and only drop Slack and push when the message left the unibox rather than on any insert error 2026-09-23 07:46:49 -07:00
Matthew Meszaros d91f23853b Merge pull request #662 from warmbly/fix/imap-search-date-refusal
feat: read the IMAP backfill window from INTERNALDATE when a server refuses a quoted SEARCH date (Seznam.cz)
2026-09-23 14:40:31 +00:00
Matthew Meszaros 96bebbea0e feat: clear the IMAP selection before SELECT is written, switch to the INTERNALDATE scan only on a refusal against a folder that stayed selected, and skip the scan cache without UIDVALIDITY 2026-09-23 07:36:25 -07:00
Matthew Meszaros 1c734411a3 feat: keep warmup out of Unibox notifications and the unread badge: tie reply notifications to their unibox message (notifications.unibox_email_id, migrations 000202-000204) so they are removed with it and read when it is read, link them to the conversation, count the badge as unread Inbox conversations without snoozed ones and refetch it instead of incrementing, hold a live arrival from the sender of an unconfirmed warmup send until its id is known, and never send warmup without a token (#659) 2026-09-23 07:30:09 -07:00
Matthew Meszaros 90213a77be feat: read the IMAP backfill window from INTERNALDATE when a server refuses a quoted SEARCH date (Seznam.cz), cached per folder, plus Czech folder names and mailbox/troubleshooting docs 2026-09-23 07:29:53 -07:00
Matthew Meszaros 95934eb697 Merge pull request #657 from warmbly/feature/open-tracking-device-client
feat: show the device and mail client behind every open and click, with image proxies reported as device hidden instead of their fake browser and location
v0.5.13
2026-09-23 09:11:52 +00:00
Matthew Meszaros c99747ea0f feat: renumber the engagement reading migration to 000201 after main released its own 000199 and 000200 2026-09-23 02:07:14 -07:00
Matthew Meszaros 331aeb4db3 Merge origin/main into feature/open-tracking-device-client 2026-09-23 02:06:04 -07:00
Matthew Meszaros fd96a8c47c Merge pull request #654 from warmbly/fix/stale-state-after-mailbox-removal
feat: close Advisor findings about a mailbox, campaign or step inside its delete transaction, keep re-evaluating workspaces that still hold open findings after their last mailbox is gone, re-evaluate the Advisor right after a mailbox change or a campaign/step delete with coalesced reruns, and refresh the unread badge, inbox, campaigns, analytics and Advisor caches on every mailbox removal including a teammate's
2026-09-23 09:06:00 +00:00
Matthew Meszaros 714bd6fe11 Merge pull request #658 from warmbly/fix/millionverifier-reverification-source
feat: queue a contact re-verify ahead of the backlog whatever its evidence or manual verdict while the current verdict stands, count MillionVerifier renewing subscription credits, let a paid verifier's fresh answer outrank mail older than 30 days, and show Verified with MillionVerifier plus a live Re-verify button on the contact Deliverability card
2026-09-23 05:40:08 +00:00
Matthew Meszaros f632a2fe6f feat: document that a click carries client_type app when a mail app made the request itself, in the timeline origin, the campaign surfaces breakdown and the OpenAPI schema 2026-09-22 22:39:59 -07:00
Matthew Meszaros 727ee432cb feat: keep a manual verdict set while a requested verification check runs, restore a lapsed evidence override from the row's own check status so a check landing mid-rescore wins, give member re-verify requests at most half of each verification batch while the backlog has work, and compare rescores against the stored verification status 2026-09-22 22:35:10 -07:00
Matthew Meszaros 19eb68ecd5 feat: re-read stored opens and clicks by the live origin rules in batched, resumable consumer passes under an advisory lock instead of a boot-time SQL backfill, never read a proxy string on a click as Apple Mail or Gmail, keep recognising Outlook, Proton Mail, Yahoo Mail and HEY by name, show the mail app behind a click in the expanded timeline row, and note that other iOS mail apps count as Apple Mail 2026-09-22 22:31:27 -07:00
Matthew Meszaros 3cf743a0cd Merge remote-tracking branch 'origin/main' into fix/millionverifier-reverification-source 2026-09-22 22:17:04 -07:00
Matthew Meszaros 72272cfbe7 feat: queue a contact re-verify ahead of the backlog whatever its evidence or manual verdict while the current verdict stands, count MillionVerifier renewing subscription credits, let a paid verifier's fresh answer outrank mail older than 30 days, keep what each check said, and show Verified with MillionVerifier plus a live Re-verify button on the contact Deliverability card 2026-09-22 22:17:04 -07:00
Matthew Meszaros eca5416a6f Merge origin/main into feature/open-tracking-device-client 2026-09-22 22:16:51 -07:00
Matthew Meszaros d44fd38d90 feat: show the device and mail client behind every open and click (iPhone · Apple Mail app, Windows PC · Outlook app, Gmail · device hidden) from a new mailclient detector that recognises Gmail, Yahoo, Apple MPP, HEY, Fastmail and Seznam image proxies instead of reporting their fake browser and data-centre location, record app vs webmail and device_hidden on the open and click logs, backfill stored opens by the same rules, let the logs accept the scanner reason, and surface it on the contact timeline, a new How they read overview, the live campaign feed, recent activity, the campaign Device breakdown (surfaces), webhooks and realtime 2026-09-22 22:16:51 -07:00
Matthew Meszaros c75b3b3b0d Merge pull request #651 from warmbly/feature/import-existing-custom-fields
feat: map import columns onto the workspace's existing custom fields
2026-09-23 04:45:33 +00:00
Matthew Meszaros 543e982d52 feat: map a column of addresses to Email before existing custom fields can claim it, and ask TypeSafe about import columns only when the Email column has a real header of its own so a contact's row is never read as headers 2026-09-22 21:42:27 -07:00
Matthew Meszaros 7813d77efc feat: send nothing to TypeSafe when an import's header row holds an address, date or number, skip placeholder Column N headers, accept only the options each column was offered, never infer Subscribed, Categories or Email, prefer an exact existing field name before a folded match on the server as the client does, compute value kinds once per preview, and make Enter in the empty field search a no-op 2026-09-22 21:29:22 -07:00
Matthew Meszaros c35e05c9eb Merge pull request #652 from warmbly/feature/sending-window-timezone
feat: give each workspace a timezone that mailbox warmup and campaign sending windows follow by default, with a Timezones control centre on Settings > Profile and the first-email delay moved into campaign Settings
2026-09-23 03:42:59 +00:00
Matthew Meszaros e4de4b35dd Merge pull request #653 from warmbly/fix/api-bind-errors-650
feat: name what is wrong with a request body, and make every CLI command send the body its endpoint binds
2026-09-23 03:40:32 +00:00
Matthew Meszaros 25652476ba feat: store the timezone a new workspace is created with, return a mailbox's own and workspace timezone from its PATCH, pin following campaigns and mailboxes to the workspace zone on the 000198 down migration, page through every campaign and mailbox before the Timezones summaries and Set all, let the campaign wizard and onboarding pick up a workspace zone that loads late, and qualify the workspace timezone copy to mailboxes that follow it 2026-09-22 20:38:18 -07:00
Matthew Meszaros 9b47f91e89 feat: name a request-body time that is not RFC 3339 in the bind refusal (documented in the error-codes table) and cover warmbly campaign add-step and edit-step in the CLI body test against the sequence update struct 2026-09-22 20:35:15 -07:00
Matthew Meszaros 7a86186f5b feat: close Advisor findings about a mailbox, campaign or step inside its delete transaction, keep re-evaluating workspaces that still hold open findings after their last mailbox is gone, re-evaluate the Advisor right after a mailbox change or a campaign/step delete with coalesced reruns, and refresh the unread badge, inbox, campaigns, analytics and Advisor caches on every mailbox removal including a teammate's 2026-09-22 20:29:13 -07:00
Matthew Meszaros 0e97ccc88d feat: make every warmbly CLI command send the body its endpoint binds (contact create, mailbox send and set-tracking, form set-domain, campaign test, task due dates, advisor snooze, warmup appeal, integration push, oauth-app scopes, corrected inbox and suppression examples, automations and webhook edit documented as full writes), pinned by a test that decodes each body strictly into the server struct, and let POST /v1/campaigns/:id/steps take the PATCH fields as an optional body so add-step no longer creates a blank step 2026-09-22 20:26:34 -07:00
Matthew Meszaros c1acded32c feat: place import columns no header matched with one TypeSafe Jev choice call per preview (headers, value kinds and field names only, never a cell; 0.70 confidence floor, one column per field, 4s fallback to the deterministic mapping), map a column of addresses to Email by its values, report inferred_columns on both import previews, mark them in the mapper, and document what is sent in data control 2026-09-22 20:22:40 -07:00
Matthew Meszaros 6cadcc725d feat: answer every public request-body bind failure with a 400 that names the problem (empty body, JSON syntax error with its byte offset, wrong JSON type for the body or a named field, missing or out-of-range fields by json key) instead of a blanket malformed-JSON message or a 500, accept a single contact object on POST /v1/contacts as the CLIs send it, and drop the API-key lookup cache whose 300ns TTL made it a Redis round trip that saved nothing 2026-09-22 20:21:41 -07:00
Matthew Meszaros 38f8382cf8 Merge remote-tracking branch 'origin/main' into feature/sending-window-timezone 2026-09-22 20:13:55 -07:00
Matthew Meszaros 45c045a5bb feat: give each workspace a timezone that mailbox warmup and campaign sending windows follow by default (organizations.timezone, migration 000198), let campaigns and mailboxes follow it or pin their own, add a Timezones control centre on Settings > Profile with inline per-campaign and per-mailbox zones, default new workspaces and the campaign wizard to the browser zone, expose effective_timezone on campaigns, and move the first-email delay from the Schedule tab and wizard into campaign Settings > First email 2026-09-22 20:13:55 -07:00
Matthew Meszaros 2bdbfe5f68 feat: list the workspace's existing custom fields in the contact import and Google Sheets column mapper (searchable, with inline create), auto-map headers to existing fields ignoring case and separators in one shared server-side suggester, flag new fields, near-duplicates and columns sharing a field, and document the matching 2026-09-22 20:07:57 -07:00
Matthew Meszaros d11b7822c7 Merge pull request #648 from warmbly/feature/imap-folder-exclusion
feat: let an IMAP mailbox exclude folders from sync so a folder another tool fills never reaches the unified inbox
v0.5.12
2026-09-22 12:50:42 +00:00
Matthew Meszaros 1520da2fa8 feat: look up moved mail against each skipped folder with one SELECT per folder and cap the reconciliation by searches rather than rows, never settle a row whose lookup failed, refuse a skip name that is a saved folder the matcher keeps and purge only what it will stop following, drop the map entries of parked arrivals too, ignore UIDVALIDITY 0 when matching a rename into the skipped subtree, carry the listing memo and pending mark across a rename, ask before ticking a folder in the drawer since imported mail is removed, share one inbox-deleted publisher between the consumer's removal paths, and say in the CLI help that an emptied list does not restore removed mail 2026-09-22 05:45:38 -07:00
Matthew Meszaros ee9f5bf84e feat: make every skipped-folder purge drop the message map entries and parked arrivals with the rows so a message can be imported again if it moves back, persist each folder's delimiter (migration 000197) so the backend purge matches the same subfolders and case the worker skips, fail the mailbox load closed when the skip list cannot be read, mark a folder renamed into the skipped subtree as skipped, never remove a row re-fetched this pass, cap the reconciliation at 50 searches per pass and continue next pass, publish one EMAIL_DELETED after a folder purge, and resolve the account once for GET /emails/:id/sync 2026-09-22 05:33:56 -07:00
Matthew Meszaros ad353b385a feat: key the IMAP departure check on the previous listing's count and UIDNEXT per folder instead of the stored cursor, since a walked folder's cursor now advances to the SELECT view and a server whose view lags its STATUS would read as departures every pass; the fake listing in the worker tests returns a copy so a second pass still sees the skipped folder 2026-09-22 05:20:06 -07:00
Matthew Meszaros 9a7ef088cf Merge remote-tracking branch 'origin/main' into feature/imap-folder-exclusion 2026-09-22 05:17:37 -07:00
Matthew Meszaros 5a967cc3ce feat: let an IMAP mailbox exclude folders from sync (email_accounts.sync_skip_folders, migration 000196) so a folder another tool fills never reaches the unified inbox: the worker drops skipped folders and their subfolders before the walk, retires an already-synced one with its stored mail, and removes mail that later moves into one only when its Message-ID is found there; PUT /emails/:id/sync and the drawer's Sync card set the list, GET reports it with the server's folder list, warmbly mailbox skip-folders mirrors it, with docs, OpenAPI and error-code invalid_sync_folder 2026-09-22 05:15:49 -07:00
Matthew Meszaros 00a0a67e0b Merge pull request #647 from warmbly/fix/unibox-sent-folder-messages
feat: advance IMAP folder sync cursors to the selected view and drop the message-map entry when NEW_EMAIL fails to publish (#645)
2026-09-22 12:03:11 +00:00