replace gmail resync with Gmail REST API, remove mbsync dependency

First sync still uses IMAP with app password. Subsequent syncs use
Gmail API history.list + messages.get with OAuth for faster, more
reliable incremental sync. Dispatch gmail-sync handler for gmail
accounts instead of generic email-sync. Show sync button for synced
accounts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 07:24:44 +00:00
co-authored by Claude Opus 4.6
parent ee1b816d66
commit 24ac7ac796
5 changed files with 382 additions and 489 deletions
+4 -2
View File
@@ -47,7 +47,7 @@ accountsRouter.get('/', async (ctx) => {
const jobs = await listAllJobs();
activeJobAccountIds = new Set(
jobs
.filter((j) => j.type === 'email-sync' && (j.status === 'queued' || j.status === 'running'))
.filter((j) => (j.type === 'email-sync' || j.type === 'gmail-sync') && (j.status === 'queued' || j.status === 'running'))
.map((j) => (j.meta as Record<string, unknown> | undefined)?.emailAccountId as number)
.filter(Boolean),
);
@@ -148,9 +148,11 @@ accountsRouter.post('/:id/sync', async (ctx) => {
// Set status immediately so the UI reflects the queued state
await updateEmailAccountStatus(id, 'queued');
const jobType = account.provider === 'gmail' ? 'gmail-sync' : 'email-sync';
const job = await enqueueJob({
lane: 'email',
type: 'email-sync',
type: jobType,
userId: user.email,
meta: {
emailAccountId: id,