HandleAlias (#10156)

If a user has microsoft aliases, they will be taken into account, in a
similar way as we did for google
This commit is contained in:
Guillim
2025-02-12 14:22:13 +01:00
committed by GitHub
parent 2b24bf43a4
commit f3586d4989
5 changed files with 167 additions and 2 deletions

View File

@ -0,0 +1,41 @@
import { Injectable } from '@nestjs/common';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider';
@Injectable()
export class MicrosoftEmailAliasManagerService {
constructor(
private readonly microsoftClientProvider: MicrosoftClientProvider,
) {}
public async getHandleAliases(
connectedAccount: ConnectedAccountWorkspaceEntity,
) {
const microsoftClient =
await this.microsoftClientProvider.getMicrosoftClient(connectedAccount);
const response = await microsoftClient
.api('/me?$select=proxyAddresses')
.get()
.catch((error) => {
throw new Error(`Failed to fetch email aliases: ${error.message}`);
});
const proxyAddresses = response.proxyAddresses;
const handleAliases =
proxyAddresses
?.filter((address) => {
return address.startsWith('SMTP:') === false;
})
.map((address) => {
return address.replace('smtp:', '').toLowerCase();
})
.filter((address) => {
return address !== '';
}) || [];
return handleAliases;
}
}

View File

@ -0,0 +1,9 @@
export const microsoftGraphMeResponseWithProxyAddresses = {
'@odata.context':
'https://graph.microsoft.com/v1.0/$metadata#users(proxyAddresses)/$entity',
proxyAddresses: [
'SMTP:bertrand1@domain.onmicrosoft.com',
'smtp:bertrand2@domain.onmicrosoft.com',
'smtp:bertrand3@otherdomain.com',
],
};

View File

@ -1,12 +1,19 @@
import { Module } from '@nestjs/common';
import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service';
import { MicrosoftEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/microsoft/microsoft-email-alias-manager.service';
import { EmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/services/email-alias-manager.service';
import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module';
import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider';
@Module({
imports: [OAuth2ClientManagerModule],
providers: [EmailAliasManagerService, GoogleEmailAliasManagerService],
providers: [
EmailAliasManagerService,
GoogleEmailAliasManagerService,
MicrosoftEmailAliasManagerService,
MicrosoftClientProvider,
],
exports: [EmailAliasManagerService],
})
export class EmailAliasManagerModule {}

View File

@ -0,0 +1,102 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ConnectedAccountProvider } from 'twenty-shared';
import { Repository } from 'typeorm';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service';
import { MicrosoftEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/microsoft/microsoft-email-alias-manager.service';
import { microsoftGraphMeResponseWithProxyAddresses } from 'src/modules/connected-account/email-alias-manager/drivers/microsoft/mocks/microsoft-api-examples';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider';
import { EmailAliasManagerService } from './email-alias-manager.service';
describe('Email Alias Manager Service', () => {
let emailAliasManagerService: EmailAliasManagerService;
let microsoftEmailAliasManagerService: MicrosoftEmailAliasManagerService;
let connectedAccountRepository: Partial<
Repository<ConnectedAccountWorkspaceEntity>
>;
beforeEach(async () => {
connectedAccountRepository = {
update: jest.fn().mockResolvedValue((arg) => arg),
};
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: TwentyORMManager,
useValue: {
getRepository: jest
.fn()
.mockResolvedValue(connectedAccountRepository),
},
},
EmailAliasManagerService,
{
provide: GoogleEmailAliasManagerService,
useValue: {},
},
MicrosoftEmailAliasManagerService,
{
provide: MicrosoftClientProvider,
useValue: {
getMicrosoftClient: jest.fn().mockResolvedValue({
api: jest.fn().mockReturnValue({
get: jest
.fn()
.mockResolvedValue(
microsoftGraphMeResponseWithProxyAddresses,
),
}),
}),
},
},
],
}).compile();
emailAliasManagerService = module.get<EmailAliasManagerService>(
EmailAliasManagerService,
);
microsoftEmailAliasManagerService =
module.get<MicrosoftEmailAliasManagerService>(
MicrosoftEmailAliasManagerService,
);
});
it('Service should be defined', () => {
expect(emailAliasManagerService).toBeDefined();
});
describe('Refresh handle aliases for Microsoft', () => {
it('Should refresh Microsoft handle aliases successfully', async () => {
const mockConnectedAccount: Partial<ConnectedAccountWorkspaceEntity> = {
id: 'test-id',
provider: ConnectedAccountProvider.MICROSOFT,
refreshToken: 'test-refresh-token',
};
const expectedAliases =
'bertrand2@domain.onmicrosoft.com,bertrand3@otherdomain.com';
jest.spyOn(microsoftEmailAliasManagerService, 'getHandleAliases');
await emailAliasManagerService.refreshHandleAliases(
mockConnectedAccount as ConnectedAccountWorkspaceEntity,
);
expect(
microsoftEmailAliasManagerService.getHandleAliases,
).toHaveBeenCalledWith(mockConnectedAccount);
expect(connectedAccountRepository.update).toHaveBeenCalledWith(
{ id: mockConnectedAccount.id },
{
handleAliases: expectedAliases,
},
);
});
});
});

View File

@ -2,12 +2,14 @@ import { Injectable } from '@nestjs/common';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service';
import { MicrosoftEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/microsoft/microsoft-email-alias-manager.service';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
@Injectable()
export class EmailAliasManagerService {
constructor(
private readonly googleEmailAliasManagerService: GoogleEmailAliasManagerService,
private readonly microsoftEmailAliasManagerService: MicrosoftEmailAliasManagerService,
private readonly twentyORMManager: TwentyORMManager,
) {}
@ -18,7 +20,11 @@ export class EmailAliasManagerService {
switch (connectedAccount.provider) {
case 'microsoft':
return;
handleAliases =
await this.microsoftEmailAliasManagerService.getHandleAliases(
connectedAccount,
);
break;
case 'google':
handleAliases =
await this.googleEmailAliasManagerService.getHandleAliases(