( client: ImapFlow, config: ImapWebhookConfig, requestId: string, logger: Logger )
| 237 | } |
| 238 | |
| 239 | async function fetchNewEmails( |
| 240 | client: ImapFlow, |
| 241 | config: ImapWebhookConfig, |
| 242 | requestId: string, |
| 243 | logger: Logger |
| 244 | ) { |
| 245 | const emails: Array<{ |
| 246 | uid: number |
| 247 | mailboxPath: string |
| 248 | envelope: FetchMessageObject['envelope'] |
| 249 | bodyStructure: FetchMessageObject['bodyStructure'] |
| 250 | source?: Buffer |
| 251 | }> = [] |
| 252 | |
| 253 | const mailboxes = getMailboxesToCheck(config) |
| 254 | const latestUidByMailbox: Record<string, number> = { ...(config.lastProcessedUidByMailbox || {}) } |
| 255 | const uidValidityByMailbox: Record<string, string> = { ...(config.uidValidityByMailbox || {}) } |
| 256 | |
| 257 | const maxEmails = config.maxEmailsPerPoll || 25 |
| 258 | let totalEmailsCollected = 0 |
| 259 | |
| 260 | for (const mailboxPath of mailboxes) { |
| 261 | if (totalEmailsCollected >= maxEmails) break |
| 262 | |
| 263 | try { |
| 264 | const mailbox = await client.mailboxOpen(mailboxPath) |
| 265 | |
| 266 | const currentUidValidity = mailbox.uidValidity.toString() |
| 267 | const storedUidValidity = uidValidityByMailbox[mailboxPath] |
| 268 | |
| 269 | if (storedUidValidity && storedUidValidity !== currentUidValidity) { |
| 270 | logger.warn( |
| 271 | `[${requestId}] UIDVALIDITY changed for ${mailboxPath} (${storedUidValidity} -> ${currentUidValidity}), discarding stored UID` |
| 272 | ) |
| 273 | delete latestUidByMailbox[mailboxPath] |
| 274 | } |
| 275 | uidValidityByMailbox[mailboxPath] = currentUidValidity |
| 276 | |
| 277 | let searchCriteria: Record<string, unknown> = { unseen: true } |
| 278 | if (config.searchCriteria) { |
| 279 | if (typeof config.searchCriteria === 'object') { |
| 280 | searchCriteria = config.searchCriteria |
| 281 | } else if (typeof config.searchCriteria === 'string') { |
| 282 | try { |
| 283 | searchCriteria = JSON.parse(config.searchCriteria) |
| 284 | } catch { |
| 285 | logger.warn(`[${requestId}] Invalid search criteria JSON, using default`) |
| 286 | } |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | const lastUidForMailbox = latestUidByMailbox[mailboxPath] |
| 291 | |
| 292 | if (lastUidForMailbox) { |
| 293 | searchCriteria = { ...searchCriteria, uid: `${lastUidForMailbox + 1}:*` } |
| 294 | } |
| 295 | |
| 296 | if (config.lastCheckedTimestamp) { |
no test coverage detected