fix smtp outbound persist message (#20276)

`APPEND` used display name `Sent` instead of `INBOX.Sent`
Fix is to use mailbox path, extreacted this as a utility, all services
are consistent now.

/closes #20267
This commit is contained in:
neo773
2026-05-05 17:58:03 +05:30
committed by GitHub
parent ff65b5001d
commit a3f2fafce6
5 changed files with 60 additions and 14 deletions
@@ -14,6 +14,7 @@ import { shouldCreateFolderByDefault } from 'src/modules/messaging/message-folde
import { shouldSyncFolderByDefault } from 'src/modules/messaging/message-folder-manager/utils/should-sync-folder-by-default.util';
import { ImapClientProvider } from 'src/modules/messaging/message-import-manager/drivers/imap/providers/imap-client.provider';
import { ImapFindSentFolderService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-find-sent-folder.service';
import { getImapFolderPath } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/get-imap-folder-path.util';
import { getStandardFolderByRegex } from 'src/modules/messaging/message-import-manager/drivers/utils/get-standard-folder-by-regex';
@Injectable()
@@ -163,15 +164,9 @@ export class ImapGetAllFoldersService implements MessageFolderDriver {
return false;
}
const isDuplicate = existingFolders.some((folder) => {
const folderPath = folder?.externalId?.split(':')[0];
if (!isDefined(folderPath)) {
return false;
}
return folderPath === mailbox.path;
});
const isDuplicate = existingFolders.some(
(folder) => getImapFolderPath(folder?.externalId) === mailbox.path,
);
return !isDuplicate;
}
@@ -15,7 +15,7 @@ import { ImapMessageListFetchErrorHandler } from 'src/modules/messaging/message-
import { ImapSyncService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-sync.service';
import { createSyncCursor } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/create-sync-cursor.util';
import { extractMailboxState } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/extract-mailbox-state.util';
import { parseMessageId } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-message-id.util';
import { getImapFolderPath } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/get-imap-folder-path.util';
import { parseSyncCursor } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-sync-cursor.util';
import { type GetMessageListsArgs } from 'src/modules/messaging/message-import-manager/types/get-message-lists-args.type';
import {
@@ -79,7 +79,7 @@ export class ImapGetMessageListService {
client: ImapFlow,
folder: MessageFolder,
): Promise<GetOneMessageListResponse> {
const folderPath = parseMessageId(folder.externalId ?? '')?.folder;
const folderPath = getImapFolderPath(folder.externalId);
if (!isDefined(folderPath)) {
throw new MessageImportDriverException(
@@ -157,7 +157,7 @@ export class ImapGetMessageListService {
client: ImapFlow,
folder: MessageFolder,
): Promise<boolean> {
const folderPath = parseMessageId(folder.externalId ?? '')?.folder;
const folderPath = getImapFolderPath(folder.externalId);
const previousCursor = parseSyncCursor(folder.syncCursor);
if (!isDefined(folderPath) || !isDefined(previousCursor)) {
@@ -0,0 +1,25 @@
import { getImapFolderPath } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/get-imap-folder-path.util';
describe('getImapFolderPath', () => {
it('extracts the path from a `path:uidValidity` externalId', () => {
expect(getImapFolderPath('INBOX.Sent:1768984533')).toBe('INBOX.Sent');
});
it('returns the externalId unchanged when it has no uidValidity suffix', () => {
expect(getImapFolderPath('INBOX')).toBe('INBOX');
});
it('preserves colons inside the path and only strips the trailing uidValidity', () => {
expect(getImapFolderPath('Foo:Bar:42')).toBe('Foo:Bar');
});
it('returns the externalId unchanged when the trailing segment is non-numeric', () => {
expect(getImapFolderPath('Project: Updates')).toBe('Project: Updates');
});
it('returns null for empty, null, or undefined input', () => {
expect(getImapFolderPath('')).toBeNull();
expect(getImapFolderPath(null)).toBeNull();
expect(getImapFolderPath(undefined)).toBeNull();
});
});
@@ -0,0 +1,23 @@
import { isNonEmptyString } from '@sniptt/guards';
export const getImapFolderPath = (
externalId: string | null | undefined,
): string | null => {
if (!isNonEmptyString(externalId)) {
return null;
}
const lastColonIndex = externalId.lastIndexOf(':');
if (lastColonIndex === -1) {
return externalId;
}
const trailingSegment = externalId.slice(lastColonIndex + 1);
if (!/^\d+$/.test(trailingSegment)) {
return externalId;
}
return externalId.slice(0, lastColonIndex);
};
@@ -12,6 +12,7 @@ import { MessageFolderEntity } from 'src/engine/metadata-modules/message-folder/
import { type ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
import { ImapClientProvider } from 'src/modules/messaging/message-import-manager/drivers/imap/providers/imap-client.provider';
import { ImapFindDraftsFolderService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-find-drafts-folder.service';
import { getImapFolderPath } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/get-imap-folder-path.util';
import { SmtpClientProvider } from 'src/modules/messaging/message-import-manager/drivers/smtp/providers/smtp-client.provider';
import { type SendMessageInput } from 'src/modules/messaging/message-outbound-manager/types/send-message-input.type';
import { type SendMessageResult } from 'src/modules/messaging/message-outbound-manager/types/send-message-result.type';
@@ -76,8 +77,10 @@ export class ImapSmtpMessageOutboundService implements MessageOutboundDriver {
});
}
if (isDefined(sentFolder) && isDefined(sentFolder.name)) {
await imapClient.append(sentFolder.name, messageBuffer);
const sentFolderPath = getImapFolderPath(sentFolder?.externalId);
if (isDefined(sentFolderPath)) {
await imapClient.append(sentFolderPath, messageBuffer);
}
await this.imapClientProvider.closeClient(imapClient);