Skip to content

Commit fc88aff

Browse files
committed
fix outlook well known folder id resolution
1 parent 3feb636 commit fc88aff

File tree

1 file changed

+101
-4
lines changed

1 file changed

+101
-4
lines changed

apps/sim/lib/webhooks/outlook-polling-service.ts

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,19 @@ async function fetchNewOutlookEmails(
359359
const data = await response.json()
360360
const emails = data.value || []
361361

362-
const filteredEmails = filterEmailsByFolder(emails, config)
362+
let resolvedFolderIds: Map<string, string> | undefined
363+
if (config.folderIds && config.folderIds.length > 0) {
364+
const hasWellKnownFolders = config.folderIds.some(isWellKnownFolderName)
365+
if (hasWellKnownFolders) {
366+
resolvedFolderIds = await resolveWellKnownFolderIds(
367+
accessToken,
368+
config.folderIds,
369+
requestId
370+
)
371+
}
372+
}
373+
374+
const filteredEmails = filterEmailsByFolder(emails, config, resolvedFolderIds)
363375

364376
logger.info(
365377
`[${requestId}] Fetched ${emails.length} emails, ${filteredEmails.length} after filtering`
@@ -373,18 +385,103 @@ async function fetchNewOutlookEmails(
373385
}
374386
}
375387

388+
const OUTLOOK_WELL_KNOWN_FOLDERS = new Set([
389+
'inbox',
390+
'drafts',
391+
'sentitems',
392+
'deleteditems',
393+
'junkemail',
394+
'archive',
395+
'outbox',
396+
])
397+
398+
function isWellKnownFolderName(folderId: string): boolean {
399+
return OUTLOOK_WELL_KNOWN_FOLDERS.has(folderId.toLowerCase())
400+
}
401+
402+
async function resolveWellKnownFolderId(
403+
accessToken: string,
404+
folderName: string,
405+
requestId: string
406+
): Promise<string | null> {
407+
try {
408+
const response = await fetch(`https://graph.microsoft.com/v1.0/me/mailFolders/${folderName}`, {
409+
headers: {
410+
Authorization: `Bearer ${accessToken}`,
411+
'Content-Type': 'application/json',
412+
},
413+
})
414+
415+
if (!response.ok) {
416+
logger.warn(
417+
`[${requestId}] Failed to resolve well-known folder '${folderName}': ${response.status}`
418+
)
419+
return null
420+
}
421+
422+
const folder = await response.json()
423+
return folder.id || null
424+
} catch (error) {
425+
logger.error(`[${requestId}] Error resolving well-known folder '${folderName}':`, error)
426+
return null
427+
}
428+
}
429+
430+
async function resolveWellKnownFolderIds(
431+
accessToken: string,
432+
folderIds: string[],
433+
requestId: string
434+
): Promise<Map<string, string>> {
435+
const resolvedIds = new Map<string, string>()
436+
437+
const wellKnownFolders = folderIds.filter(isWellKnownFolderName)
438+
if (wellKnownFolders.length === 0) {
439+
return resolvedIds
440+
}
441+
442+
const resolutions = await Promise.all(
443+
wellKnownFolders.map(async (folderName) => {
444+
const actualId = await resolveWellKnownFolderId(accessToken, folderName, requestId)
445+
return { folderName, actualId }
446+
})
447+
)
448+
449+
for (const { folderName, actualId } of resolutions) {
450+
if (actualId) {
451+
resolvedIds.set(folderName.toLowerCase(), actualId)
452+
}
453+
}
454+
455+
logger.info(
456+
`[${requestId}] Resolved ${resolvedIds.size}/${wellKnownFolders.length} well-known folders`
457+
)
458+
459+
return resolvedIds
460+
}
461+
376462
function filterEmailsByFolder(
377463
emails: OutlookEmail[],
378-
config: OutlookWebhookConfig
464+
config: OutlookWebhookConfig,
465+
resolvedFolderIds?: Map<string, string>
379466
): OutlookEmail[] {
380467
if (!config.folderIds || !config.folderIds.length) {
381468
return emails
382469
}
383470

471+
const actualFolderIds = config.folderIds.map((configFolder) => {
472+
if (resolvedFolderIds && isWellKnownFolderName(configFolder)) {
473+
const resolvedId = resolvedFolderIds.get(configFolder.toLowerCase())
474+
if (resolvedId) {
475+
return resolvedId
476+
}
477+
}
478+
return configFolder
479+
})
480+
384481
return emails.filter((email) => {
385482
const emailFolderId = email.parentFolderId
386-
const hasMatchingFolder = config.folderIds!.some((configFolder) =>
387-
emailFolderId.toLowerCase().includes(configFolder.toLowerCase())
483+
const hasMatchingFolder = actualFolderIds.some(
484+
(folderId) => emailFolderId.toLowerCase() === folderId.toLowerCase()
388485
)
389486

390487
return config.folderFilterBehavior === 'INCLUDE' ? hasMatchingFolder : !hasMatchingFolder

0 commit comments

Comments
 (0)