Child folders followup (#15526)
This commit is contained in:
+30
-9
@@ -5,6 +5,11 @@ import { ListResponse, type ImapFlow } from 'imapflow';
|
||||
|
||||
import { getImapSentFolderCandidatesByRegex } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/get-sent-folder-candidates-by-regex.util';
|
||||
|
||||
type SentFolderResult = {
|
||||
name: string;
|
||||
path: string;
|
||||
} | null;
|
||||
|
||||
/**
|
||||
* Service to find sent folder using IMAP special-use flags
|
||||
*
|
||||
@@ -19,7 +24,7 @@ import { getImapSentFolderCandidatesByRegex } from 'src/modules/messaging/messag
|
||||
export class ImapFindSentFolderService {
|
||||
private readonly logger = new Logger(ImapFindSentFolderService.name);
|
||||
|
||||
public async findSentFolder(client: ImapFlow): Promise<string | null> {
|
||||
public async findSentFolder(client: ImapFlow): Promise<SentFolderResult> {
|
||||
try {
|
||||
const list = await client.list();
|
||||
|
||||
@@ -60,7 +65,7 @@ export class ImapFindSentFolderService {
|
||||
private async findSentFolderBySpecialUse(
|
||||
client: ImapFlow,
|
||||
list: ListResponse[],
|
||||
): Promise<string | null> {
|
||||
): Promise<SentFolderResult> {
|
||||
for (const folder of list) {
|
||||
if (folder.specialUse && folder.specialUse.includes('\\Sent')) {
|
||||
this.logger.log(
|
||||
@@ -73,7 +78,10 @@ export class ImapFindSentFolderService {
|
||||
);
|
||||
|
||||
if (messageCount > 0) {
|
||||
return folder.path;
|
||||
return {
|
||||
name: folder.name,
|
||||
path: folder.path,
|
||||
};
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
@@ -90,25 +98,38 @@ export class ImapFindSentFolderService {
|
||||
private async findSentFolderByRegexCandidates(
|
||||
client: ImapFlow,
|
||||
list: ListResponse[],
|
||||
): Promise<string | null> {
|
||||
): Promise<SentFolderResult> {
|
||||
const regexCandidateFolders = getImapSentFolderCandidatesByRegex(list);
|
||||
|
||||
for (const folder of regexCandidateFolders) {
|
||||
const messageCount = await this.getFolderMessageCount(client, folder);
|
||||
const messageCount = await this.getFolderMessageCount(
|
||||
client,
|
||||
folder.path,
|
||||
);
|
||||
|
||||
if (messageCount > 0) {
|
||||
this.logger.log(`Selected sent folder via pattern match: ${folder}`);
|
||||
this.logger.log(
|
||||
`Selected sent folder via pattern match: ${folder.path}`,
|
||||
);
|
||||
|
||||
return folder;
|
||||
return {
|
||||
name: folder.name,
|
||||
path: folder.path,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (regexCandidateFolders.length > 0) {
|
||||
this.logger.log(
|
||||
`Using first regex candidate sent folder: ${regexCandidateFolders[0]} (no messages found in any regex candidate)`,
|
||||
`Using first regex candidate sent folder: ${regexCandidateFolders[0].path} (no messages found in any regex candidate)`,
|
||||
);
|
||||
|
||||
return regexCandidateFolders[0];
|
||||
const folder = regexCandidateFolders[0];
|
||||
|
||||
return {
|
||||
name: folder.name,
|
||||
path: folder.path,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+8
-1
@@ -41,10 +41,17 @@ export class ImapGetMessageListService {
|
||||
for (const folder of messageFolders) {
|
||||
this.logger.log(`Processing folder: ${folder.name}`);
|
||||
|
||||
const folderPath = folder.externalId?.split(':')[0];
|
||||
|
||||
if (!folderPath) {
|
||||
this.logger.warn(`Folder ${folder.name} has no path. Skipping.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.getMessageList(
|
||||
client,
|
||||
folder.name,
|
||||
folderPath,
|
||||
folder,
|
||||
);
|
||||
|
||||
|
||||
+32
-12
@@ -3,7 +3,7 @@ import { type ListResponse } from 'imapflow';
|
||||
import { getImapSentFolderCandidatesByRegex } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/get-sent-folder-candidates-by-regex.util';
|
||||
|
||||
function makeList(paths: string[]): ListResponse[] {
|
||||
return paths.map((p) => ({ path: p }) as ListResponse);
|
||||
return paths.map((p) => ({ path: p, name: p }) as ListResponse);
|
||||
}
|
||||
|
||||
describe('getSentFolderCandidatesByRegex', () => {
|
||||
@@ -18,7 +18,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(englishVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(englishVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(englishVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches French variants', () => {
|
||||
@@ -26,7 +28,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(frenchVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(frenchVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(frenchVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches German variants', () => {
|
||||
@@ -34,7 +38,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(germanVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(germanVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(germanVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Spanish variants', () => {
|
||||
@@ -42,7 +48,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(spanishVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(spanishVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(spanishVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Portuguese variants', () => {
|
||||
@@ -50,7 +58,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(portugueseVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(portugueseVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(portugueseVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Italian variants', () => {
|
||||
@@ -58,7 +68,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(italianVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(italianVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(italianVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Korean variant', () => {
|
||||
@@ -66,7 +78,7 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(koreanVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(koreanVariants);
|
||||
expect(result.map((r) => r.path)).toEqual(koreanVariants);
|
||||
});
|
||||
|
||||
it('matches Japanese variants', () => {
|
||||
@@ -74,7 +86,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(japaneseVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(japaneseVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(japaneseVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Polish variants', () => {
|
||||
@@ -82,7 +96,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(polishVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(polishVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(polishVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Russian variants', () => {
|
||||
@@ -95,7 +111,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(russianVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(russianVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(russianVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('matches Gmail special folder', () => {
|
||||
@@ -103,7 +121,9 @@ describe('getSentFolderCandidatesByRegex', () => {
|
||||
const input = makeList(gmailVariants);
|
||||
const result = getImapSentFolderCandidatesByRegex(input);
|
||||
|
||||
expect(result).toEqual(expect.arrayContaining(gmailVariants));
|
||||
expect(result.map((r) => r.path)).toEqual(
|
||||
expect.arrayContaining(gmailVariants),
|
||||
);
|
||||
});
|
||||
|
||||
it('does not match unrelated folders', () => {
|
||||
|
||||
+9
-2
@@ -5,7 +5,7 @@ import { getStandardFolderByRegex } from 'src/modules/messaging/message-import-m
|
||||
|
||||
export function getImapSentFolderCandidatesByRegex(
|
||||
list: ListResponse[],
|
||||
): string[] {
|
||||
): { name: string; path: string }[] {
|
||||
const regexCandidateFolders: string[] = [];
|
||||
|
||||
for (const folder of list) {
|
||||
@@ -16,5 +16,12 @@ export function getImapSentFolderCandidatesByRegex(
|
||||
}
|
||||
}
|
||||
|
||||
return regexCandidateFolders;
|
||||
return regexCandidateFolders.map((folderPath) => {
|
||||
const folder = list.find((folder) => folder.path === folderPath);
|
||||
|
||||
return {
|
||||
name: folder?.name ?? folderPath,
|
||||
path: folderPath,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user