Skip to content

Commit 64cd60d

Browse files
feat(outlook): add outlook webhook provider (#874)
* feat(outlook): add outlook webhook provider * remove useless files * cron to one minute * Update apps/sim/lib/webhooks/utils.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update apps/sim/lib/webhooks/outlook-polling-service.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update apps/sim/lib/webhooks/outlook-polling-service.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * fix lint * fix type error: --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
1 parent 696ef12 commit 64cd60d

File tree

14 files changed

+1379
-14
lines changed

14 files changed

+1379
-14
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { nanoid } from 'nanoid'
2+
import { type NextRequest, NextResponse } from 'next/server'
3+
import { verifyCronAuth } from '@/lib/auth/internal'
4+
import { Logger } from '@/lib/logs/console/logger'
5+
import { acquireLock, releaseLock } from '@/lib/redis'
6+
import { pollOutlookWebhooks } from '@/lib/webhooks/outlook-polling-service'
7+
8+
const logger = new Logger('OutlookPollingAPI')
9+
10+
export const dynamic = 'force-dynamic'
11+
export const maxDuration = 180 // Allow up to 3 minutes for polling to complete
12+
13+
const LOCK_KEY = 'outlook-polling-lock'
14+
const LOCK_TTL_SECONDS = 180 // Same as maxDuration (3 min)
15+
16+
export async function GET(request: NextRequest) {
17+
const requestId = nanoid()
18+
logger.info(`Outlook webhook polling triggered (${requestId})`)
19+
20+
let lockValue: string | undefined
21+
22+
try {
23+
const authError = verifyCronAuth(request, 'Outlook webhook polling')
24+
if (authError) {
25+
return authError
26+
}
27+
28+
lockValue = requestId // unique value to identify the holder
29+
const locked = await acquireLock(LOCK_KEY, lockValue, LOCK_TTL_SECONDS)
30+
31+
if (!locked) {
32+
return NextResponse.json(
33+
{
34+
success: true,
35+
message: 'Polling already in progress – skipped',
36+
requestId,
37+
status: 'skip',
38+
},
39+
{ status: 202 }
40+
)
41+
}
42+
43+
const results = await pollOutlookWebhooks()
44+
45+
return NextResponse.json({
46+
success: true,
47+
message: 'Outlook polling completed',
48+
requestId,
49+
status: 'completed',
50+
...results,
51+
})
52+
} catch (error) {
53+
logger.error(`Error during Outlook polling (${requestId}):`, error)
54+
return NextResponse.json(
55+
{
56+
success: false,
57+
message: 'Outlook polling failed',
58+
error: error instanceof Error ? error.message : 'Unknown error',
59+
requestId,
60+
},
61+
{ status: 500 }
62+
)
63+
} finally {
64+
await releaseLock(LOCK_KEY).catch(() => {})
65+
}
66+
}

apps/sim/app/api/webhooks/route.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,40 @@ export async function POST(request: NextRequest) {
266266
}
267267
// --- End Gmail specific logic ---
268268

269+
// --- Outlook webhook setup ---
270+
if (savedWebhook && provider === 'outlook') {
271+
logger.info(
272+
`[${requestId}] Outlook provider detected. Setting up Outlook webhook configuration.`
273+
)
274+
try {
275+
const { configureOutlookPolling } = await import('@/lib/webhooks/utils')
276+
const success = await configureOutlookPolling(userId, savedWebhook, requestId)
277+
278+
if (!success) {
279+
logger.error(`[${requestId}] Failed to configure Outlook polling`)
280+
return NextResponse.json(
281+
{
282+
error: 'Failed to configure Outlook polling',
283+
details: 'Please check your Outlook account permissions and try again',
284+
},
285+
{ status: 500 }
286+
)
287+
}
288+
289+
logger.info(`[${requestId}] Successfully configured Outlook polling`)
290+
} catch (err) {
291+
logger.error(`[${requestId}] Error setting up Outlook webhook configuration`, err)
292+
return NextResponse.json(
293+
{
294+
error: 'Failed to configure Outlook webhook',
295+
details: err instanceof Error ? err.message : 'Unknown error',
296+
},
297+
{ status: 500 }
298+
)
299+
}
300+
}
301+
// --- End Outlook specific logic ---
302+
269303
const status = existingWebhooks.length > 0 ? 200 : 201
270304
return NextResponse.json({ webhook: savedWebhook }, { status })
271305
} catch (error: any) {

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export {
55
GithubConfig,
66
GmailConfig,
77
MicrosoftTeamsConfig,
8+
OutlookConfig,
89
SlackConfig,
910
StripeConfig,
1011
TelegramConfig,

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/components/sub-block/components/webhook/components/providers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export { GenericConfig } from './generic'
44
export { GithubConfig } from './github'
55
export { GmailConfig } from './gmail'
66
export { MicrosoftTeamsConfig } from './microsoftteams'
7+
export { OutlookConfig } from './outlook'
78
export { SlackConfig } from './slack'
89
export { StripeConfig } from './stripe'
910
export { TelegramConfig } from './telegram'

0 commit comments

Comments
 (0)