fix(messaging): reset sync state when IMAP/SMTP/CalDAV credentials are updated (#20405)
## Problem Updating credentials for an existing IMAP/SMTP/CalDAV connected account in **Settings → Accounts → Connection settings** has no effect on the sync. The save persists the new `connectionParameters`, but `messageChannel.syncStatus` / `messageChannel.syncStage` / `connectedAccount.authFailedAt` are left untouched, and no fetch job is queued. This matters most when the channel is in `FAILED_INSUFFICIENT_PERMISSIONS` (e.g. after Apple invalidates iCloud app-specific passwords, or on any other auth failure): `MessagingRelaunchFailedMessageChannelsCronJob` only retries `FAILED_UNKNOWN`, so the account is stuck on "Sync failed" forever despite the credentials now being correct. The only known workarounds are a direct DB update or deleting and recreating the account. #19273 fixed the frontend cache angle of credential editing; this PR fixes the backend half of the same UX (the channel state machine). ## Reproduce 1. Connect an IMAP/SMTP account. 2. Force an auth failure (e.g. revoke the app-specific password upstream). Wait until `messageChannel.syncStatus` flips to `FAILED_INSUFFICIENT_PERMISSIONS`. 3. Generate a fresh password, edit the account in **Settings → Accounts**, save. 4. Observe: account stays "Sync failed" indefinitely; `core.messageChannel.syncStatus` and `core.connectedAccount.authFailedAt` are unchanged; no IMAP connect attempt in the worker logs. ## Root cause `packages/twenty-server/src/modules/connected-account/services/imap-smtp-caldav-apis.service.ts → processAccount` saves the updated `connectionParameters` but never resets the sync state nor enqueues a fetch job. The OAuth providers handle this: | Reset step | `google-apis.service.ts` | `microsoft-apis.service.ts` | `imap-smtp-caldav-apis.service.ts` (before this PR) | |---|---|---|---| | `updateConnectedAccountOnReconnect` (clears `authFailedAt`) | yes | yes | — | | `accountsToReconnectService.removeAccountToReconnect` | yes | yes | — | | `resetAndMarkAsMessagesListFetchPending` | yes | yes | — | | Enqueue `MessagingMessageListFetchJob` | yes | yes | — | | `resetAndMarkAsCalendarEventListFetchPending` | yes | yes | — | | Enqueue `CalendarEventListFetchJob` | yes | yes | — | #12061 introduced this behaviour for Google/Microsoft. The IMAP service was added later and the equivalent reconnect plumbing was never ported. ## Fix Mirrors the Google/Microsoft pattern in `processAccount`: - **Inside** the transaction, when an account already exists: clear `authFailedAt` on the connected account. - **After** the transaction, when an existing account is being updated: - drop the account from `accountsToReconnect` user-vars, - if the message channel exists and IMAP is configured, call `resetAndMarkAsMessagesListFetchPending` and enqueue `MessagingMessageListFetchJob` (skipped while the channel is still `PENDING_CONFIGURATION`), - same logic for the calendar channel and `CalendarEventListFetchJob`. Wires `MessageChannelSyncStatusService`, `CalendarChannelSyncStatusService`, `AccountsToReconnectService` and the messaging/calendar queues into `IMAPAPIsModule`. ## Tests - Extended the existing `should preserve existing channels when updating account credentials` case to assert: `authFailedAt: null` is written within the transaction; `removeAccountToReconnect` is called with the resolved `userId`; `resetAndMarkAs*` and queue `add` are called for both channels. - New case: `should not queue fetch jobs for channels still in PENDING_CONFIGURATION`. - New case: `should not run reconnect logic when creating a brand new account`. I could not run the full server test suite locally (no `node_modules` checked out); relying on CI. ## Out of scope - Extending `UpdateConnectedAccountOnReconnectService` to a non-OAuth shape: kept inline to minimise the blast radius. Refactoring opportunity for a follow-up. - Behaviour when the user removes IMAP or CALDAV from the parameters on update (the channel currently lingers in its old state). Pre-existing and not made worse by this PR.
This commit is contained in:
committed by
GitHub
parent
a962cdc34f
commit
086830f81b
@@ -12,7 +12,10 @@ import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channe
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceEventEmitterModule } from 'src/engine/workspace-event-emitter/workspace-event-emitter.module';
|
||||
import { CalendarCommonModule } from 'src/modules/calendar/common/calendar-common.module';
|
||||
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
||||
import { ImapSmtpCalDavAPIService } from 'src/modules/connected-account/services/imap-smtp-caldav-apis.service';
|
||||
import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module';
|
||||
import { MessagingFolderSyncManagerModule } from 'src/modules/messaging/message-folder-manager/messaging-folder-sync-manager.module';
|
||||
|
||||
@Module({
|
||||
@@ -30,6 +33,9 @@ import { MessagingFolderSyncManagerModule } from 'src/modules/messaging/message-
|
||||
TwentyORMModule,
|
||||
FeatureFlagModule,
|
||||
AuthModule,
|
||||
CalendarCommonModule,
|
||||
ConnectedAccountModule,
|
||||
MessagingCommonModule,
|
||||
MessagingFolderSyncManagerModule,
|
||||
],
|
||||
providers: [ImapSmtpCalDavAPIService],
|
||||
|
||||
+166
-9
@@ -1,17 +1,28 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { ConnectedAccountProvider } from 'twenty-shared/types';
|
||||
import {
|
||||
CalendarChannelSyncStage,
|
||||
ConnectedAccountProvider,
|
||||
MessageChannelSyncStage,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { CreateCalendarChannelService } from 'src/engine/core-modules/auth/services/create-calendar-channel.service';
|
||||
import { CreateMessageChannelService } from 'src/engine/core-modules/auth/services/create-message-channel.service';
|
||||
import { type EmailAccountConnectionParameters } from 'src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.dto';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { getQueueToken } from 'src/engine/core-modules/message-queue/utils/get-queue-token.util';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { ImapSmtpCalDavAPIService } from 'src/modules/connected-account/services/imap-smtp-caldav-apis.service';
|
||||
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
|
||||
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service';
|
||||
import { CalendarEventListFetchJob } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job';
|
||||
import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service';
|
||||
import { ImapSmtpCalDavAPIService } from 'src/modules/connected-account/services/imap-smtp-caldav-apis.service';
|
||||
import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service';
|
||||
import { MessagingMessageListFetchJob } from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job';
|
||||
import { SyncMessageFoldersService } from 'src/modules/messaging/message-folder-manager/services/sync-message-folders.service';
|
||||
|
||||
jest.mock('uuid', () => ({
|
||||
@@ -43,9 +54,9 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
|
||||
const mockTransactionManagerSave = jest.fn();
|
||||
const mockTransactionManager = {
|
||||
getRepository: jest
|
||||
.fn()
|
||||
.mockReturnValue({ save: mockTransactionManagerSave }),
|
||||
getRepository: jest.fn().mockReturnValue({
|
||||
save: mockTransactionManagerSave,
|
||||
}),
|
||||
};
|
||||
|
||||
const mockConnectedAccountRepository = {
|
||||
@@ -83,6 +94,26 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
createCalendarChannel: jest.fn().mockResolvedValue('mocked-uuid'),
|
||||
};
|
||||
|
||||
const mockMessageQueueService = {
|
||||
add: jest.fn(),
|
||||
};
|
||||
|
||||
const mockCalendarQueueService = {
|
||||
add: jest.fn(),
|
||||
};
|
||||
|
||||
const mockAccountsToReconnectService = {
|
||||
removeAccountToReconnect: jest.fn(),
|
||||
};
|
||||
|
||||
const mockMessagingChannelSyncStatusService = {
|
||||
resetAndMarkAsMessagesListFetchPending: jest.fn(),
|
||||
};
|
||||
|
||||
const mockCalendarChannelSyncStatusService = {
|
||||
resetAndMarkAsCalendarEventListFetchPending: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
@@ -134,6 +165,26 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
syncMessageFolders: jest.fn().mockResolvedValue([]),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getQueueToken(MessageQueue.messagingQueue),
|
||||
useValue: mockMessageQueueService,
|
||||
},
|
||||
{
|
||||
provide: getQueueToken(MessageQueue.calendarQueue),
|
||||
useValue: mockCalendarQueueService,
|
||||
},
|
||||
{
|
||||
provide: AccountsToReconnectService,
|
||||
useValue: mockAccountsToReconnectService,
|
||||
},
|
||||
{
|
||||
provide: MessageChannelSyncStatusService,
|
||||
useValue: mockMessagingChannelSyncStatusService,
|
||||
},
|
||||
{
|
||||
provide: CalendarChannelSyncStatusService,
|
||||
useValue: mockCalendarChannelSyncStatusService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@@ -185,6 +236,7 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
connectionParameters: baseInput.connectionParameters,
|
||||
userWorkspaceId: 'user-workspace-id',
|
||||
workspaceId: 'workspace-id',
|
||||
authFailedAt: null,
|
||||
});
|
||||
|
||||
expect(
|
||||
@@ -212,11 +264,13 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
const existingMessageChannel = {
|
||||
id: 'existing-message-channel-id',
|
||||
connectedAccountId: 'existing-account-id',
|
||||
syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING,
|
||||
} as MessageChannelEntity;
|
||||
|
||||
const existingCalendarChannel = {
|
||||
id: 'existing-calendar-channel-id',
|
||||
connectedAccountId: 'existing-account-id',
|
||||
syncStage: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_PENDING,
|
||||
} as CalendarChannelEntity;
|
||||
|
||||
mockConnectedAccountRepository.findOne.mockResolvedValue(existingAccount);
|
||||
@@ -236,6 +290,16 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
|
||||
const inputWithConnectedAccountId = {
|
||||
...baseInput,
|
||||
connectionParameters: {
|
||||
...baseInput.connectionParameters,
|
||||
CALDAV: {
|
||||
host: 'caldav.example.com',
|
||||
port: 443,
|
||||
secure: true,
|
||||
username: 'test@example.com',
|
||||
password: 'password',
|
||||
},
|
||||
} as EmailAccountConnectionParameters,
|
||||
connectedAccountId: 'existing-account-id',
|
||||
};
|
||||
|
||||
@@ -245,9 +309,10 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
id: 'existing-account-id',
|
||||
handle: 'test@example.com',
|
||||
provider: ConnectedAccountProvider.IMAP_SMTP_CALDAV,
|
||||
connectionParameters: baseInput.connectionParameters,
|
||||
connectionParameters: inputWithConnectedAccountId.connectionParameters,
|
||||
userWorkspaceId: 'user-workspace-id',
|
||||
workspaceId: 'workspace-id',
|
||||
authFailedAt: null,
|
||||
});
|
||||
|
||||
expect(
|
||||
@@ -256,6 +321,97 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
expect(
|
||||
mockCreateCalendarChannelService.createCalendarChannel,
|
||||
).not.toHaveBeenCalled();
|
||||
|
||||
expect(
|
||||
mockAccountsToReconnectService.removeAccountToReconnect,
|
||||
).toHaveBeenCalledWith('user-id', 'workspace-id', 'existing-account-id');
|
||||
|
||||
expect(
|
||||
mockMessagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending,
|
||||
).toHaveBeenCalledWith(['existing-message-channel-id'], 'workspace-id');
|
||||
expect(mockMessageQueueService.add).toHaveBeenCalledWith(
|
||||
MessagingMessageListFetchJob.name,
|
||||
{
|
||||
workspaceId: 'workspace-id',
|
||||
messageChannelId: 'existing-message-channel-id',
|
||||
},
|
||||
);
|
||||
|
||||
expect(
|
||||
mockCalendarChannelSyncStatusService.resetAndMarkAsCalendarEventListFetchPending,
|
||||
).toHaveBeenCalledWith(['existing-calendar-channel-id'], 'workspace-id');
|
||||
expect(mockCalendarQueueService.add).toHaveBeenCalledWith(
|
||||
CalendarEventListFetchJob.name,
|
||||
{
|
||||
workspaceId: 'workspace-id',
|
||||
calendarChannelId: 'existing-calendar-channel-id',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should leave channels in PENDING_CONFIGURATION untouched', async () => {
|
||||
const existingAccount = {
|
||||
id: 'existing-account-id',
|
||||
handle: 'test@example.com',
|
||||
userWorkspaceId: 'user-workspace-id',
|
||||
provider: ConnectedAccountProvider.IMAP_SMTP_CALDAV,
|
||||
} as ConnectedAccountEntity;
|
||||
|
||||
const existingMessageChannel = {
|
||||
id: 'existing-message-channel-id',
|
||||
connectedAccountId: 'existing-account-id',
|
||||
syncStage: MessageChannelSyncStage.PENDING_CONFIGURATION,
|
||||
} as MessageChannelEntity;
|
||||
|
||||
mockConnectedAccountRepository.findOne.mockResolvedValue(existingAccount);
|
||||
mockMessageChannelRepository.findOne.mockResolvedValue(
|
||||
existingMessageChannel,
|
||||
);
|
||||
mockCalendarChannelRepository.findOne.mockResolvedValue(null);
|
||||
mockWorkspaceMemberRepository.findOne.mockResolvedValue({
|
||||
id: 'workspace-member-id',
|
||||
userId: 'user-id',
|
||||
});
|
||||
mockUserWorkspaceRepository.findOne.mockResolvedValue({
|
||||
id: 'user-workspace-id',
|
||||
});
|
||||
|
||||
await service.processAccount({
|
||||
...baseInput,
|
||||
connectedAccountId: 'existing-account-id',
|
||||
});
|
||||
|
||||
expect(
|
||||
mockMessagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(mockMessageQueueService.add).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not run reconnect logic when creating a brand new account', async () => {
|
||||
mockConnectedAccountRepository.findOne.mockResolvedValue(null);
|
||||
mockMessageChannelRepository.findOne.mockResolvedValue(null);
|
||||
mockCalendarChannelRepository.findOne.mockResolvedValue(null);
|
||||
mockWorkspaceMemberRepository.findOne.mockResolvedValue({
|
||||
id: 'workspace-member-id',
|
||||
userId: 'user-id',
|
||||
});
|
||||
mockUserWorkspaceRepository.findOne.mockResolvedValue({
|
||||
id: 'user-workspace-id',
|
||||
});
|
||||
|
||||
await service.processAccount(baseInput);
|
||||
|
||||
expect(
|
||||
mockAccountsToReconnectService.removeAccountToReconnect,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(
|
||||
mockMessagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(
|
||||
mockCalendarChannelSyncStatusService.resetAndMarkAsCalendarEventListFetchPending,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(mockMessageQueueService.add).not.toHaveBeenCalled();
|
||||
expect(mockCalendarQueueService.add).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should only create message channel when only IMAP is configured', async () => {
|
||||
@@ -455,6 +611,7 @@ describe('ImapSmtpCalDavAPIService', () => {
|
||||
connectionParameters: baseInput.connectionParameters,
|
||||
userWorkspaceId: 'user-workspace-id',
|
||||
workspaceId: 'workspace-id',
|
||||
authFailedAt: null,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+70
-2
@@ -1,7 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { ConnectedAccountProvider } from 'twenty-shared/types';
|
||||
import {
|
||||
CalendarChannelSyncStage,
|
||||
ConnectedAccountProvider,
|
||||
MessageChannelSyncStage,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import { EntityManager, Repository } from 'typeorm';
|
||||
@@ -10,6 +14,9 @@ import { NotFoundError } from 'src/engine/core-modules/graphql/utils/graphql-err
|
||||
import { CreateCalendarChannelService } from 'src/engine/core-modules/auth/services/create-calendar-channel.service';
|
||||
import { CreateMessageChannelService } from 'src/engine/core-modules/auth/services/create-message-channel.service';
|
||||
import { type EmailAccountConnectionParameters } from 'src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.dto';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
@@ -18,8 +25,19 @@ import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspac
|
||||
import { getWorkspaceContext } from 'src/engine/twenty-orm/storage/orm-workspace-context.storage';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { resolveRolePermissionConfig } from 'src/engine/twenty-orm/utils/resolve-role-permission-config.util';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
import {
|
||||
CalendarEventListFetchJob,
|
||||
type CalendarEventListFetchJobData,
|
||||
} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job';
|
||||
import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service';
|
||||
import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service';
|
||||
import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service';
|
||||
import {
|
||||
MessagingMessageListFetchJob,
|
||||
type MessagingMessageListFetchJobData,
|
||||
} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job';
|
||||
import { SyncMessageFoldersService } from 'src/modules/messaging/message-folder-manager/services/sync-message-folders.service';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class ImapSmtpCalDavAPIService {
|
||||
@@ -33,9 +51,16 @@ export class ImapSmtpCalDavAPIService {
|
||||
private readonly messageChannelRepository: Repository<MessageChannelEntity>,
|
||||
@InjectRepository(UserWorkspaceEntity)
|
||||
private readonly userWorkspaceRepository: Repository<UserWorkspaceEntity>,
|
||||
@InjectMessageQueue(MessageQueue.messagingQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
@InjectMessageQueue(MessageQueue.calendarQueue)
|
||||
private readonly calendarQueueService: MessageQueueService,
|
||||
private readonly createMessageChannelService: CreateMessageChannelService,
|
||||
private readonly createCalendarChannelService: CreateCalendarChannelService,
|
||||
private readonly syncMessageFoldersService: SyncMessageFoldersService,
|
||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||
private readonly messagingChannelSyncStatusService: MessageChannelSyncStatusService,
|
||||
private readonly calendarChannelSyncStatusService: CalendarChannelSyncStatusService,
|
||||
) {}
|
||||
|
||||
async getImapSmtpCaldavConnectedAccount(
|
||||
@@ -154,6 +179,7 @@ export class ImapSmtpCalDavAPIService {
|
||||
connectionParameters: input.connectionParameters,
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
authFailedAt: null,
|
||||
});
|
||||
|
||||
if (shouldCreateMessageChannel) {
|
||||
@@ -176,6 +202,14 @@ export class ImapSmtpCalDavAPIService {
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(existingAccount)) {
|
||||
await this.accountsToReconnectService.removeAccountToReconnect(
|
||||
member.userId,
|
||||
workspaceId,
|
||||
newOrExistingAccountId,
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldCreateMessageChannel) {
|
||||
const newMessageChannel = await this.messageChannelRepository.findOne(
|
||||
{
|
||||
@@ -195,6 +229,40 @@ export class ImapSmtpCalDavAPIService {
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(existingMessageChannel) &&
|
||||
isDefined(input.connectionParameters.IMAP) &&
|
||||
existingMessageChannel.syncStage !==
|
||||
MessageChannelSyncStage.PENDING_CONFIGURATION
|
||||
) {
|
||||
await this.messagingChannelSyncStatusService.resetAndMarkAsMessagesListFetchPending(
|
||||
[existingMessageChannel.id],
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
||||
MessagingMessageListFetchJob.name,
|
||||
{ workspaceId, messageChannelId: existingMessageChannel.id },
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(existingCalendarChannel) &&
|
||||
isDefined(input.connectionParameters.CALDAV) &&
|
||||
existingCalendarChannel.syncStage !==
|
||||
CalendarChannelSyncStage.PENDING_CONFIGURATION
|
||||
) {
|
||||
await this.calendarChannelSyncStatusService.resetAndMarkAsCalendarEventListFetchPending(
|
||||
[existingCalendarChannel.id],
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.calendarQueueService.add<CalendarEventListFetchJobData>(
|
||||
CalendarEventListFetchJob.name,
|
||||
{ workspaceId, calendarChannelId: existingCalendarChannel.id },
|
||||
);
|
||||
}
|
||||
|
||||
return newOrExistingAccountId;
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user