mirror of
https://github.com/warmbly/warmbly.git
synced 2026-09-06 00:01:24 +00:00
Files
feat: resume a reloaded Gmail mailbox from its saved history checkpoint instead of the never-written email_accounts.last_id column, which no code in the repository ever assigns so it is NULL forever and every worker restart, deploy, crash or docker compose up handed the mailbox a zero cursor that re-bootstrapped straight to Gmail's current historyId and silently skipped everything that arrived since the last successful sync, unrecoverably because the history API only walks forward from the id it is given, by threading the EmailHistoryIDRepository the consumer already writes to into emailService as the Google counterpart of the existing WireGraphDelta cursor plumbing for Outlook, reading it in buildAddWorkerEmail through a lastHistoryFor helper that prefers the live checkpoint, still falls back to last_id for rows carrying a value from before the checkpoint table existed, and returns zero only when genuinely nothing is known so a first-time mailbox bootstraps a fresh baseline, plus tests covering the precedence and every fallback including an unwired repository (#121)
feat: stop a freshly connected mailbox being silently excluded from every campaign send, by making an unset mailbox timezone representable as the empty string the campaign scheduler already checks for, since email_accounts.timezone defaulted to 'UTC' while campaigns.timezone defaults to 'Europe/London' and nothing in the OAuth or SMTP onboarding paths ever set either, so a brand new mailbox looked deliberately placed in UTC, was compared against the differing campaign zone and dropped by the hardcoded 8am-8pm business-hours gate whenever the current UTC hour fell outside it, emptying the candidate pool and failing the campaign start, adding a migration that changes the column default and converts existing 'UTC' rows because until now no API field, dashboard control or onboarding path could set that column at all so every such row is the old default rather than a choice, adding the missing Timezone field to UpdateEmail with IANA validation so the setting the sending-behaviour UI already tells people to change is finally reachable and an unloadable zone is rejected instead of being silently coerced to UTC by the scheduler, and replacing the misleading 'no active email accounts found for campaign's email tags' response for a pool that exists but is entirely gated out with a distinct message naming the real cause, via an ErrNoEligibleMailbox that wraps ErrNoEmailAccounts so the three callers that pause a campaign on it are unaffected (#126) (#125) (#127)
feat: make the inbound mail pipeline work end to end by never publishing the eventbus partition key as Nats-Msg-Id (JetStream deduped every event after the first per mailbox), fetching IMAP message bodies after the outer FETCH closes instead of nesting one inside it (which deadlocked sync on the first message), wrapping NEW_EMAIL in JobEventNewEmail across all three providers so the consumer stops nil-derefing, coalescing nil arrays before the NOT NULL unibox columns, sealing validation credentials on a copy so stored SMTP/IMAP passwords are not double encrypted, routing the email task type to the user email handler, and returning false instead of closing a nil conn in VerifySMTP (#88)