internal-messages-backend-and-frontend (#10291)

fixes https://github.com/twentyhq/twenty/issues/10263
fixes https://github.com/twentyhq/twenty/issues/10262 also
This commit is contained in:
Guillim
2025-02-19 15:02:10 +01:00
committed by GitHub
parent 7636def54d
commit ad9af65898
5 changed files with 159 additions and 5 deletions

View File

@ -44,7 +44,7 @@ export const SettingsAccountsBlocklistSection = () => {
<Section>
<H2Title
title={t`Blocklist`}
description={t`Exclude the following people and domains from my email sync`}
description={t`Exclude the following people and domains from my email sync. Internal conversations will not be imported`}
/>
<SettingsAccountsBlocklistInput
blockedEmailOrDomainList={blocklist.map((item) => item.handle)}

View File

@ -140,7 +140,8 @@ export class MessagingMessagesImportService {
);
const messagesToSave = filterEmails(
[messageChannel.handle, ...connectedAccount.handleAliases.split(',')],
messageChannel.handle,
[...connectedAccount.handleAliases.split(',')],
allMessages,
blocklist.map((blocklistItem) => blocklistItem.handle),
);

View File

@ -0,0 +1,70 @@
import { MessageWithParticipants } from 'src/modules/messaging/message-import-manager/types/message';
export const messagingGetMessagesServiceGetMessages = [
{
externalId: 'AA-work-emails-internal',
subject: 'Test email for microsoft',
receivedAt: new Date('2025-01-09T09:54:37.000Z'),
text: 'Just a test',
headerMessageId: '<d45b9f1c@PR0P264MB2911.FRAP264.PROD.OUTLOOK.COM>',
messageThreadExternalId: 'AAQkAGZlMDQ1NjU5Lk=',
direction: 'OUTGOING',
participants: [
{
role: 'from',
handle: 'from@acme.com',
displayName: 'From',
},
{
role: 'to',
handle: 'to@acme.com',
displayName: 'To',
},
],
attachments: [],
},
{
externalId: 'AA-work-emails-external',
subject: 'Test email for microsoft',
receivedAt: new Date('2025-01-09T09:54:37.000Z'),
text: 'Just a test',
headerMessageId: '<d45b9f1c@PR0P264MB2911.FRAP264.PROD.OUTLOOK.COM>',
messageThreadExternalId: 'AAQkAGZlMDQ1NjU5Lk=',
direction: 'OUTGOING',
participants: [
{
role: 'from',
handle: 'from@acme.com',
displayName: 'From',
},
{
role: 'to',
handle: 'to@external.com',
displayName: 'To',
},
],
attachments: [],
},
{
externalId: 'AA-personal-emails',
subject: 'Sign in to your Microsoft Learn account for more features',
receivedAt: new Date('2025-01-28T19:01:21.000Z'),
text: 'Learn with interactive sandboxes, curated collections, and bookmarks',
headerMessageId: '<AC70000@mails.microsoft.com>',
messageThreadExternalId: 'AAQkAGZlMDQ1NNc=',
direction: 'INCOMING',
participants: [
{
role: 'from',
handle: 'learn@mails.microsoft.com',
displayName: 'Microsoft Learn',
},
{
role: 'to',
handle: 'to@gmail.com',
displayName: 'To',
},
],
attachments: [],
},
] as MessageWithParticipants[];

View File

@ -0,0 +1,51 @@
import { messagingGetMessagesServiceGetMessages } from 'src/modules/messaging/message-import-manager/utils/__mocks__/messages';
import { filterEmails } from 'src/modules/messaging/message-import-manager/utils/filter-emails.util';
describe('filterEmails', () => {
it('Should not filter at all if primary handle is a personal email', () => {
const primaryHandle = 'guillim@gmail.com';
const messages = messagingGetMessagesServiceGetMessages;
const filteredMessages = filterEmails(primaryHandle, [], messages, []);
expect(filteredMessages).toEqual(messages);
});
it('Should not filter out if at least one email is from a different domain', () => {
const primaryHandle = 'guillim@acme.com';
const messages = messagingGetMessagesServiceGetMessages.filter(
(message) => message.externalId === 'AA-work-emails-external',
);
const filteredMessages = filterEmails(primaryHandle, [], messages, []);
expect(filteredMessages).toEqual(messages);
});
it('Should filter out same domain emails', () => {
const primaryHandle = 'guillim@acme.com';
const messages = messagingGetMessagesServiceGetMessages.filter(
(message) => message.externalId === 'AA-work-emails-internal',
);
const filteredMessages = filterEmails(primaryHandle, [], messages, []);
expect(filteredMessages).toEqual([]);
});
it('Should filter messages with participant from the blocklist', () => {
const primaryHandle = 'guillim@acme.com';
const messages = messagingGetMessagesServiceGetMessages.filter(
(message) => message.externalId === 'AA-work-emails-internal',
);
const blocklist = ['to@acme.com'];
const filteredMessages = filterEmails(
primaryHandle,
[],
messages,
blocklist,
);
expect(filteredMessages).toEqual([]);
});
});

View File

@ -1,17 +1,26 @@
import { isEmailBlocklisted } from 'src/modules/blocklist/utils/is-email-blocklisted.util';
import { MessageWithParticipants } from 'src/modules/messaging/message-import-manager/types/message';
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
import { isWorkEmail } from 'src/utils/is-work-email';
// Todo: refactor this into several utils
export const filterEmails = (
messageChannelHandles: string[],
primaryHandle: string,
handleAliases: string[],
messages: MessageWithParticipants[],
blocklist: string[],
) => {
return filterOutBlocklistedMessages(
messageChannelHandles,
const messagesWithoutBlocklisted = filterOutBlocklistedMessages(
[primaryHandle, ...handleAliases],
filterOutIcsAttachments(messages),
blocklist,
);
if (isWorkEmail(primaryHandle)) {
return filterOutInternals(primaryHandle, messagesWithoutBlocklisted);
}
return messagesWithoutBlocklisted;
};
const filterOutBlocklistedMessages = (
@ -46,3 +55,26 @@ const filterOutIcsAttachments = (messages: MessageWithParticipants[]) => {
);
});
};
const filterOutInternals = (
primaryHandle: string,
messages: MessageWithParticipants[],
) => {
return messages.filter((message) => {
if (!message.participants) {
return true;
}
const primaryHandleDomain = getDomainNameByEmail(primaryHandle);
const isAllHandlesFromSameDomain = message.participants.every(
(participant) =>
getDomainNameByEmail(participant.handle) === primaryHandleDomain,
);
if (isAllHandlesFromSameDomain) {
return false;
}
return true;
});
};