Matthew Meszaros
8db2409a81
feat: read dialTCP and smtpsEgress once at the top of DialSubmission and hand them to the dial goroutines and closeLosers, so the 465/587 race's goroutines that outlive the call never read the package variables a later dial or test may be replacing
2026-10-03 06:24:09 +02:00
Matthew Meszaros
45786649c7
feat: let the incoming reply repair query use idx_tasks_message_id and idx_contacts_org_email by matching each In-Reply-To in its bracketed and bare forms against the raw task Message-ID and resolving the mailbox's workspace before the contact address match, so a batch over the 45-day window finishes instead of hitting the statement timeout every minute
2026-10-03 06:07:20 +02:00
Matthew Meszaros
a09ba27b0c
feat: confirm a missing SPF or DMARC record with the sending domain's own authoritative nameservers before reporting it, look names up fully qualified so a resolver failure is never retried under the host's search domains and read as not found, look up internationalized domains in ASCII, record the verdict when a mailbox manager presses Check in the drawer, and show an unanswered lookup as unverified rather than missing
2026-10-02 06:13:37 -07:00
Matthew Meszaros
50d50d0fbc
Merge pull request #793 from warmbly/fix/inbox-follow-up-sweep-paging
...
feat: page the hourly inbox follow-up sweep through each mailbox newest first in bounded keyset pages that resolve thread state only for the threads on the page, resume each workspace's cycle from a cursor persisted in inbox_follow_up_sweeps under a per-pass time budget, check recently active threads first every pass, and add the unibox_emails (email_id, internal_date, id) index the walk reads
2026-10-02 06:33:14 +00:00
Matthew Meszaros
39285173f1
feat: never move the follow-up changed-thread watermark past a page it failed to read, step past a failing page, thread or unreadable mailbox only after three failures spanning at least an hour, fence sweep state saves on the lease owner alone and log a takeover, clear a stale failure count once the walk moves on, and note that imported unibox rows keep their source ingested_at
2026-10-01 23:20:45 -07:00
Matthew Meszaros
0bcbab91ac
Merge remote-tracking branch 'origin/main' into fix/inbox-follow-up-sweep-paging
...
# Conflicts:
# internal/app/orgtransfer/spec.go
2026-10-01 23:20:32 -07:00
Matthew Meszaros
b2310f5d4b
feat: renumber the inbox follow-up sweep migrations from 000243-000247 to 000245-000249 so they follow 000243_campaign_task_subject and 000244_unibox_rail_layout on main instead of colliding with them
2026-10-02 08:15:42 +02:00
Matthew Meszaros
e883e60c3d
Merge pull request #795 from warmbly/fix/worker-465-egress
...
feat: name a worker's own blocked outbound 465 instead of blaming the mailbox's server
2026-10-02 06:12:30 +00:00
Matthew Meszaros
e79551867f
feat: have a worker learn from its own dials when its network blocks outbound 465, dial 587 at once there, tell a mailbox whose server only takes 465 that the block is on the sending side instead of blaming its server, report the block on every heartbeat as the node's last error, rename the admin Workers filter to Has node error, and document the outbound ports a worker needs
2026-10-02 08:02:36 +02:00
Matthew Meszaros
244b2e6613
feat: renumber the unibox rail layout migration to 000244 after main took 000243
2026-10-01 22:59:25 -07:00
Matthew Meszaros
b8a8ec4743
Merge remote-tracking branch 'origin/main' into feat/unibox-rail-layout-per-member
2026-10-01 22:58:31 -07:00
Matthew Meszaros
1aeb45773b
feat: check threads changed since each workspace's last follow-up pass by when the message was stored (new unibox_emails.ingested_at) or its verdict written, behind a persisted watermark, give each workspace's sweep a single leased walker whose saves are conditional on the lease, stop the cursor at the last thread whose label was written and step past a page or thread after three consecutive failures, keep the cycle running when the changed-thread check fails, and accept warmblyctl inbox-tag follow-ups --limit as a deprecated no-op
2026-10-01 22:52:43 -07:00
Matthew Meszaros
945fadb260
Merge pull request #788 from warmbly/fix/ab-variant-thread-subject
...
feat: thread campaign follow-ups on the A/B arm each contact was actually sent by recording every send's rendered subject on campaign_tasks.subject (migration 000243) and reusing it verbatim in ThreadParentForLead, and list the opening step's variant subjects in the follow-up composer
2026-10-02 05:46:33 +00:00
Matthew Meszaros
1e1acef6f4
Merge pull request #791 from warmbly/fix/unibox-refresh-load
...
feat: coalesce and dedupe unibox realtime refreshes in useRealtimeEvents, forward TanStack Query abort signals through every unibox client and the shared Request helper with cancellations kept out of error handling, share one organization-scoped unibox overview computation per second with in-flight dedup and write-time invalidation, bound interactive unibox reads at 30s including pool wait, and log slow pgxpool connection acquisitions
2026-10-02 05:46:17 +00:00
Matthew Meszaros
bce968646f
feat: thread campaign follow-ups on the A/B arm each contact was actually sent by recording every send's rendered subject on campaign_tasks.subject (migration 000243) and reusing it verbatim in ThreadParentForLead, and list the opening step's variant subjects in the follow-up composer
2026-10-01 22:41:11 -07:00
Matthew Meszaros
8f89c36756
feat: refresh the open conversation for inbox events that name only a message id, give unibox refresh keys added just before a max-wait flush a trailing flush, cancel a shared unibox overview computation once its last caller leaves and bound it and GET /unibox/overview at 30s, include scheduled sends in the coalesced inbox refresh, and word the slow pgxpool acquire log as acquire time rather than saturation
2026-10-01 22:41:00 -07:00
Matthew Meszaros
7707f6fb02
Merge pull request #789 from warmbly/fix/unibox-unread-latest-received
...
feat: mark only a conversation's newest received message unread on Mark as unread, never a sent or draft copy
2026-10-02 05:37:48 +00:00
Matthew Meszaros
54a05027cc
feat: save the unibox scope rail's favorites, row and section order and hidden rows to the member's account per workspace through a unibox_rail view with a validated layout on /me/views, synced from the dashboard store so every device shows the same rail while folds and widths stay per browser
2026-10-01 22:37:23 -07:00
Matthew Meszaros
6758bc8035
feat: page the hourly inbox follow-up sweep through each mailbox newest first in bounded keyset pages that resolve thread state only for the threads on the page, resume each workspace's cycle from a cursor persisted in inbox_follow_up_sweeps under a per-pass time budget, check recently active threads first every pass, and add the unibox_emails (email_id, internal_date, id) index the walk reads
2026-10-01 22:29:41 -07:00
Matthew Meszaros
e137530895
feat: run the jobrun scheduler tests on the testing/synctest fake clock and cover a claim that errors with or without its write landing, so each slot still runs exactly once
2026-10-01 22:29:39 -07:00
Matthew Meszaros
dc2cffd786
feat: coalesce and dedupe unibox realtime refreshes in useRealtimeEvents, forward TanStack Query abort signals through every unibox client and the shared Request helper with cancellations kept out of error handling, share one organization-scoped unibox overview computation per second with in-flight dedup and write-time invalidation, bound interactive unibox reads at 30s including pool wait, and log slow pgxpool connection acquisitions
2026-10-01 22:25:53 -07:00
Matthew Meszaros
a84b3bbbf3
feat: mark only a conversation's newest received message unread on Mark as unread, never a sent or draft copy, from the reader, the row menu, the selection bar, PATCH /unibox/seen and the mark_thread_seen AI tool, with the guide and API docs updated
2026-10-01 22:22:56 -07:00
Matthew Meszaros
7c8ed01775
feat: resume every scheduled job from its stored next_run_at after a restart instead of starting a fresh interval, run a job that came due while the process was down right after its phase offset, and claim each slot with a compare-and-swap on next_run_at so a job hosted by several processes runs once per slot
2026-10-01 22:16:16 -07:00
Matthew Meszaros
e920b61371
feat: clear a reported warmup send failure only on a confirmed delivery, word the not-loaded send failure as a possible cause, leave placement seeds out of the adopted-mailbox warmup repair, and describe send_failure as a failure reason in the API schema
2026-10-01 03:20:41 -07:00
Matthew Meszaros
a844c506a0
feat: make Warmbly Cloud warmup start and explain itself for linked mailboxes: apply the instance's warmup settings, start warmup on adopted mailboxes, read the warmup day mask Monday-first, report the last refused warmup send and the partner cap to the instance and dashboard, hand changed SMTP credentials to the cloud, refuse cleartext mailboxes at enrollment, and show cloud warmup with the warming animation and a clear Cloud marker
2026-10-01 03:01:36 -07:00
Matthew Meszaros
e25b31f992
Merge pull request #772 from warmbly/fix/unibox-template-html-body
...
feat: send a unibox template's HTML body as written by giving the compose and reply composers an HTML mode, keep that HTML in compose and reply drafts, and render the text part server-side for HTML-only sends
2026-10-01 04:22:11 +00:00
Matthew Meszaros
2a78dc1a25
Merge remote-tracking branch 'origin/main' into fix/unibox-template-html-body
2026-09-30 21:15:35 -07:00
Matthew Meszaros
a072f2a618
Merge pull request #771 from warmbly/fix/mailbox-switch-back-on
...
feat: let a switched-off mailbox be switched back on from its row menu, warmup menu, drawer, settings and the selection bar, and make the Advisor's stop-cold-sending fixes hold the mailbox from campaigns instead of switching it off
2026-10-01 04:08:07 +00:00
Matthew Meszaros
f41b377f0c
feat: offer the Advisor's campaign hold only while a mailbox is still sending cold, reseed warmup when an AI tool switches a mailbox on or starts warmup, and fix the mailbox switch's bulk selection, double clicks and revoked-mailbox hints
2026-09-30 21:02:00 -07:00
Matthew Meszaros
588591684b
feat: send a unibox template's HTML body as written by giving the compose and reply composers an HTML mode, keep that HTML in compose and reply drafts, and render the text part server-side for HTML-only sends
2026-09-30 20:46:22 -07:00
Matthew Meszaros
7ea17c0150
feat: let a switched-off mailbox be switched back on from its row menu, warmup menu, drawer, settings and the selection bar, and make the Advisor's stop-cold-sending fixes hold the mailbox from campaigns instead of switching it off
2026-09-30 20:45:42 -07:00
Matthew Meszaros
f3e9505457
feat: pass each warmup retention prune statement only the arguments it references, so the mailbox_owner_activity delete no longer fails PruneWarmupEventsBefore and the warmup_received and warmup_tokens prunes after it run, with the live retention test covering the owner activity window
2026-09-30 20:32:28 -07:00
Matthew Meszaros
fbadb837b8
feat: put a linked instance's existing Cloud redirect back when its update is refused, and say in the sending domains guide which unconfirmed checks still show Live
2026-09-30 07:40:22 -07:00
Matthew Meszaros
371eafd9da
feat: renumber the domain redirect serving migration to 000238 after main released 000237
2026-09-30 07:19:59 -07:00
Matthew Meszaros
d64adcc191
Merge remote-tracking branch 'origin/main' into feat/cloud-domain-redirects
2026-09-30 07:18:51 -07:00
Matthew Meszaros
e9b802e99c
feat: insert the received-mail CSP into the parsed document's real head, tie remote-image consent to the message it was given for, check every RevokeOnRefreshReuse error in the live test, and name the signing-key length refusal in the OpenAPI 400
2026-09-30 07:01:13 -07:00
Matthew Meszaros
7b526be901
feat: write a Cloud-served root redirect here before asking Warmbly Cloud (one workspace per domain, enforced by a unique index), roll it back on Cloud's refusal and keep it pending through an outage, release Cloud redirects no workspace here has any more from the sweep, resend a target Cloud holds stale, stop a mirrored redirect only on Cloud's definite refusals, read a proxy gateway error as transient and order the certificate and port verdicts correctly, validate linked domains with the shared hostname check, share one proxy name map, and trim comments
2026-09-30 06:59:55 -07:00
Matthew Meszaros
75f764dc67
feat: require a verified Cloud Tasks token with a pinned audience on task webhooks, manage_settings on integration OAuth and a fresh membership check at every mailbox and integration OAuth finish, user verification for passkey sign-in, ended sessions before a password reset or ban reports success, and a revoked session when a rotated refresh token is replayed; remove the internal DEK delete route, log credential path parameters by name, hold remote images in received mail until the reader loads them, add Calendly and Cal.com signing keys with inbound URL rotation, keep automation signing secrets out of connection responses, and apply the password rules to the bootstrap password
2026-09-30 06:46:24 -07:00
Matthew Meszaros
ef83f10a7e
feat: refuse a root redirect upsert that meets the domain's row held by another owner (a linked instance or the workspace) instead of rewriting it, keep the Warmbly Cloud option closed for a Cloud-served redirect once the link or offer is gone, and say in the sending domains guide that the dashboard preselects Cloud while the API keeps this instance
2026-09-30 06:29:53 -07:00
Matthew Meszaros
d457ad86e3
feat: keep Warmbly Cloud's link-token answers from ever reaching the dashboard as a 401, stop a Cloud-served redirect Cloud refuses to take back, drop a new Cloud row its own check refused, store only reach values this schema knows when mirroring a newer Cloud, read an offer-less Cloud as not serving redirects, confirm bulk moves against the server actually sent, poll the Cloud offer once a minute, and probe without keep-alive connections
2026-09-30 06:21:29 -07:00
Matthew Meszaros
41d43f64be
feat: check that a verified root redirect actually reaches visitors by opening the domain over http and https and naming what answered instead (Traefik, nginx, Caddy, a rewritten Host header, a missing certificate, a closed port) with per-proxy fix steps in the sending domain drawer, and let a self-hosted instance linked to Warmbly Cloud have Cloud serve and certify its redirects (connect in place from the redirect tab, the bulk dialog or a page banner), with Cloud-side linked-instance redirect endpoints under a per-instance limit, migration 000237, labelled tracking answers and a 503 when the redirect lookup is unavailable, and the sending domains, Warmbly Cloud, data control, install, OpenAPI, API and error code docs updated
2026-09-30 06:04:00 -07:00
Matthew Meszaros
1f0c6ca6d6
feat: send each mailbox's reply-to as a Reply-To header on campaign, unibox, test and placement mail (never warmup), record it on every campaign send attempt (tasks.reply_to, migration 000236) and credit a reply landing in that shared reply inbox to the campaign and its sending mailbox across reply attribution, the sync priority lane and copied-contact replies, show the sending mailbox on thread messages, recent activity and the reply webhook, start unibox and inbox-agent replies from the mailbox that emailed the contact, flag an untracked reply-to in mailbox settings, let the sandbox simulator answer Reply-To, and document the shared reply inbox ( #756 )
2026-09-30 05:33:34 -07:00
Matthew Meszaros
4bfebe8538
feat: write a relayed folder answer straight to the unibox row without reading it first, since the unibox GetByID marks an unread message seen and archiving unread mail must leave it unread, with a consumer test that fails on any read
2026-09-30 05:11:17 -07:00
Matthew Meszaros
b2d6d100dd
feat: relay unibox Archive, Delete and Move to inbox to the mailbox itself through a new MESSAGE_FOLDER worker command (Gmail label batchModify, Outlook well-known folder moves with the message map re-keyed around each Graph id change, IMAP MOVE after locating each message by Message-ID), answered by relayed UPDATE_FOLDER events that write only provider_folder and the moved handles, relaying every row a filing moved so an Undo right after Archive still reaches the mailbox, with a per-mailbox Mirror Archive and Delete switch (email_accounts.relay_folder_moves, migration 000235, on by default), warmup receipts, drafts and non-Gmail sent copies left in place, and the unibox, mailboxes, API, events and OpenAPI docs updated
2026-09-30 04:41:03 -07:00
Matthew Meszaros
a34e1634fc
feat: merge main into the placement comparison branch, keeping both the rendered-copy and the placement-batch sentences in the workspace export guide's placement row
2026-09-30 08:20:58 +02:00
Matthew Meszaros
d3fc3133da
feat: renumber the placement_renders migration from 000230 to 000234 so it follows 000233 on main instead of colliding with the released 000230_campaign_lead_cc
2026-09-30 08:20:39 +02:00
Matthew Meszaros
0ce8a6ee79
feat: claim each held warmup spam move with a lease, fix its verdict before applying any effect and complete it only after every sender and recipient write succeeds, so consumer replicas never charge a strike that disagrees with the recorded verdict and a failed write re-applies the same verdict
2026-09-30 07:08:40 +02:00
Matthew Meszaros
d3c0f76002
Merge remote-tracking branch 'origin/main' into calm-marlin-jks7
2026-09-30 06:52:32 +02:00
Matthew Meszaros
57a26c4ee6
feat: attribute a received warmup email moved to spam on the evidence around it before charging anyone, never for mail that arrived in spam (warmup_received.landed_spam), holding each move 30 minutes in warmup_spam_moves and deciding provider on a cross-workspace correlation or a move straight after arrival with nobody there, owner on provider-reported read, unread or star activity in mailbox_owner_activity or a repeated uncorrelated pattern in a used mailbox, nobody otherwise, weighting a spam move as one strike, withdrawing owner verdicts a later correlation explains, clearing the strikes behind a hold an admin lifts or an appeal approves, migration 000233, docs and guide
2026-09-30 06:52:32 +02:00
Matthew Meszaros
184e26a427
feat: call contact categories and inbox labels one name, Labels, across the dashboard (contacts tab moved to /app/contacts/labels with a redirect, pickers, filters, import, export, forms, segment field, timeline, and the Add label, Remove label and Label conversation automation actions), backend messages, AI tool descriptions and docs, keeping every API field name unchanged
2026-09-30 06:17:57 +02:00