diff --git a/apps/web/utils/__mocks__/email-provider.ts b/apps/web/utils/__mocks__/email-provider.ts index 3dd1e12f18..109c6fdf4a 100644 --- a/apps/web/utils/__mocks__/email-provider.ts +++ b/apps/web/utils/__mocks__/email-provider.ts @@ -36,6 +36,7 @@ export const createMockEmailProvider = ( overrides?: Partial, ): EmailProvider => ({ name: "google", + toJSON: () => ({ name: "google", type: "MockEmailProvider" }), getThreads: vi.fn().mockResolvedValue([]), getThread: vi.fn().mockResolvedValue({ id: "thread1", diff --git a/apps/web/utils/email/google.ts b/apps/web/utils/email/google.ts index f53446a6ef..b3bcd5408e 100644 --- a/apps/web/utils/email/google.ts +++ b/apps/web/utils/email/google.ts @@ -78,6 +78,10 @@ export class GmailProvider implements EmailProvider { this.client = client; } + toJSON() { + return { name: this.name, type: "GmailProvider" }; + } + async getThreads(labelId?: string): Promise { const response = await this.client.users.threads.list({ userId: "me", diff --git a/apps/web/utils/email/microsoft.ts b/apps/web/utils/email/microsoft.ts index 539a4ff7c8..630ff54d1c 100644 --- a/apps/web/utils/email/microsoft.ts +++ b/apps/web/utils/email/microsoft.ts @@ -75,6 +75,10 @@ export class OutlookProvider implements EmailProvider { this.client = client; } + toJSON() { + return { name: this.name, type: "OutlookProvider" }; + } + async getThreads(folderId?: string): Promise { const messages = await this.getMessages({ folderId }); const threadMap = new Map(); diff --git a/apps/web/utils/email/types.ts b/apps/web/utils/email/types.ts index 8d72375a33..b459024e67 100644 --- a/apps/web/utils/email/types.ts +++ b/apps/web/utils/email/types.ts @@ -43,6 +43,7 @@ export interface EmailSignature { export interface EmailProvider { readonly name: "google" | "microsoft"; + toJSON(): { name: string; type: string }; getThreads(folderId?: string): Promise; getThread(threadId: string): Promise; getLabels(): Promise; diff --git a/apps/web/utils/reply-tracker/label-helpers.ts b/apps/web/utils/reply-tracker/label-helpers.ts index 63b3849f74..4a2729ab9a 100644 --- a/apps/web/utils/reply-tracker/label-helpers.ts +++ b/apps/web/utils/reply-tracker/label-helpers.ts @@ -37,7 +37,7 @@ export async function removeConflictingThreadStatusLabels({ emailAccountId, threadId, systemType, - provider, + provider: provider.name, }, ); @@ -110,7 +110,7 @@ export async function applyThreadStatusLabel({ threadId, messageId, systemType, - provider, + provider: provider.name, }); const [dbLabels, providerLabels] = await Promise.all([ @@ -121,8 +121,8 @@ export async function applyThreadStatusLabel({ const addLabel = async () => { let targetLabel = dbLabels[systemType]; - // If we don't have both labelId and label from DB, fetch/create it - if (!targetLabel.labelId && !targetLabel.label) { + // If we don't have labelId from DB, fetch/create it + if (!targetLabel.labelId) { const label = providerLabels.find((l) => l.name === getRuleLabel(systemType)) || (await provider.createLabel(getRuleLabel(systemType))); @@ -134,16 +134,19 @@ export async function applyThreadStatusLabel({ } } - // Error only if we still don't have either field after attempting to fetch/create - if (!targetLabel.labelId && !targetLabel.label) { - logger.error("Failed to get or create target label"); + // Must have labelId to proceed + if (!targetLabel.labelId) { + logger.error("Failed to get or create target label", { + systemType, + labelName: getRuleLabel(systemType), + }); return; } return labelMessageAndSync({ provider, messageId, - labelId: targetLabel.labelId || "", + labelId: targetLabel.labelId, labelName: targetLabel.label, emailAccountId, }).catch((error) => diff --git a/version.txt b/version.txt index 582720df7d..b2eba76b4a 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v2.17.29 +v2.17.30