IMAP edge cases (#17065)
Fixes IMAP edge case. We had a maximum call stack reached crash if the array was very large for some folders. Plus some minor perf improvement. https://twenty-v7.sentry.io/issues/6997180505/events/652c69da1be944aab1c87ac2e6a06c30/
This commit is contained in:
-10
@@ -123,16 +123,6 @@ export class ImapClientProvider {
|
||||
`Connected to IMAP server for ${connectedAccount.handle}`,
|
||||
);
|
||||
|
||||
try {
|
||||
const mailboxes = await client.list();
|
||||
|
||||
this.logger.log(
|
||||
`Available mailboxes for ${connectedAccount.handle}: ${mailboxes.map((m) => m.path).join(', ')}`,
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.warn(`Failed to list mailboxes: ${error.message}`);
|
||||
}
|
||||
|
||||
return client;
|
||||
} catch (error) {
|
||||
if (timeoutId) {
|
||||
|
||||
+6
-14
@@ -140,23 +140,15 @@ export class ImapFindSentFolderService {
|
||||
folderPath: string,
|
||||
): Promise<number> {
|
||||
try {
|
||||
const lock = await client.getMailboxLock(folderPath);
|
||||
const status = await client.status(folderPath, {
|
||||
messages: true,
|
||||
});
|
||||
|
||||
try {
|
||||
const status = await client.status(folderPath, {
|
||||
messages: true,
|
||||
});
|
||||
const messageCount = status?.messages;
|
||||
|
||||
const messageCount = status?.messages;
|
||||
this.logger.debug(`Folder "${folderPath}" has ${messageCount} messages`);
|
||||
|
||||
this.logger.debug(
|
||||
`Folder "${folderPath}" has ${messageCount} messages`,
|
||||
);
|
||||
|
||||
return isNumber(messageCount) ? messageCount : 0;
|
||||
} finally {
|
||||
lock.release();
|
||||
}
|
||||
return isNumber(messageCount) ? messageCount : 0;
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`Error checking folder "${folderPath}": ${error.message}`,
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ export class ImapGetMessageListService {
|
||||
);
|
||||
|
||||
const nextCursor = createSyncCursor(
|
||||
messageUids.map((uid) => ({ uid })),
|
||||
messageUids,
|
||||
previousCursor,
|
||||
mailboxState,
|
||||
);
|
||||
|
||||
+8
-5
@@ -2,17 +2,20 @@ import { type MailboxState } from './extract-mailbox-state.util';
|
||||
import { type ImapSyncCursor } from './parse-sync-cursor.util';
|
||||
|
||||
export const createSyncCursor = (
|
||||
messages: { uid: number }[],
|
||||
messageUids: number[],
|
||||
previousCursor: ImapSyncCursor | null,
|
||||
mailboxState: MailboxState,
|
||||
): ImapSyncCursor => {
|
||||
const { uidValidity, highestModSeq } = mailboxState;
|
||||
const lastSeenUid = previousCursor?.highestUid ?? 0;
|
||||
|
||||
const highestUid =
|
||||
messages.length > 0
|
||||
? Math.max(...messages.map((message) => message.uid))
|
||||
: lastSeenUid;
|
||||
let highestUid = lastSeenUid;
|
||||
|
||||
for (let i = 0; i < messageUids.length; i++) {
|
||||
if (messageUids[i] > highestUid) {
|
||||
highestUid = messageUids[i];
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
highestUid,
|
||||
|
||||
+3
-2
@@ -3,9 +3,10 @@ export type ParsedMessageId = {
|
||||
uid: number;
|
||||
};
|
||||
|
||||
const MESSAGE_ID_REGEX = /^(.+):(\d+)$/;
|
||||
|
||||
export function parseMessageId(messageId: string): ParsedMessageId | null {
|
||||
const regex = /^(.+):(\d+)$/;
|
||||
const match = regex.exec(messageId);
|
||||
const match = MESSAGE_ID_REGEX.exec(messageId);
|
||||
|
||||
if (!match) {
|
||||
return null;
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
const NULL_CHAR_REGEX = /\0/g;
|
||||
|
||||
/**
|
||||
* Removes null characters (\0) from a string to prevent unexpected errors
|
||||
*/
|
||||
export const sanitizeString = (str: string) => {
|
||||
return str.replace(/\0/g, '');
|
||||
return str.replace(NULL_CHAR_REGEX, '');
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user