From fca71b6a93c2ebe851101907261f038068164204 Mon Sep 17 00:00:00 2001 From: Chunosov Date: Mon, 31 Mar 2025 11:00:30 +0700 Subject: [PATCH] Mail hook adjustments (#8385) Signed-off-by: Nikolay Chunosov --- server/account/src/collections/postgres.ts | 13 +++++++- services/mail/pod-inbound-mail/src/config.ts | 4 ++- .../mail/pod-inbound-mail/src/handlerMta.ts | 5 +++ services/mail/pod-inbound-mail/src/message.ts | 32 +++++++++---------- services/mail/pod-inbound-mail/src/person.ts | 13 ++++---- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/server/account/src/collections/postgres.ts b/server/account/src/collections/postgres.ts index ebbefb2b0f..a942d67f9c 100644 --- a/server/account/src/collections/postgres.ts +++ b/server/account/src/collections/postgres.ts @@ -643,7 +643,8 @@ export class PostgresAccountDB implements AccountDB { this.getV2Migration2(), this.getV2Migration3(), this.getV3Migration(), - this.getV4Migration() + this.getV4Migration(), + this.getV4Migration1() ] } @@ -878,4 +879,14 @@ export class PostgresAccountDB implements AccountDB { ` ] } + + private getV4Migration1 (): [string, string] { + return [ + 'account_db_v4_remove_mailbox_account_fk', + ` + ALTER TABLE ${this.ns}.mailbox + DROP CONSTRAINT IF EXISTS mailbox_account_fk; + ` + ] + } } diff --git a/services/mail/pod-inbound-mail/src/config.ts b/services/mail/pod-inbound-mail/src/config.ts index 46ff3fbcad..2a4450a9cb 100644 --- a/services/mail/pod-inbound-mail/src/config.ts +++ b/services/mail/pod-inbound-mail/src/config.ts @@ -21,6 +21,7 @@ interface Config { secret: string accountsUrl: string workspaceUrl: string + ignoredAddresses: string[] } const config: Config = { @@ -32,7 +33,8 @@ const config: Config = { return process.env.WORKSPACE_URL } throw Error('WORKSPACE_URL env var is not set') - })() + })(), + ignoredAddresses: process.env.IGNORED_ADDRESSES?.split(',') ?? [] } export default config diff --git a/services/mail/pod-inbound-mail/src/handlerMta.ts b/services/mail/pod-inbound-mail/src/handlerMta.ts index 4eb4a60653..100c96a4ba 100644 --- a/services/mail/pod-inbound-mail/src/handlerMta.ts +++ b/services/mail/pod-inbound-mail/src/handlerMta.ts @@ -17,6 +17,7 @@ import { readEml, ReadedEmlJson } from 'eml-parse-js' import { Request, Response } from 'express' import { htmlToMarkup } from '@hcengineering/text-html' import { createMessages } from './message' +import config from './config' interface MtaMessage { envelope: { @@ -38,6 +39,10 @@ export async function handleMtaHook (req: Request, res: Response): Promise const mta: MtaMessage = req.body const from = { address: mta.envelope.from.address, name: '' } + if (config.ignoredAddresses.includes(from.address)) { + console.log(`Ignoring message from ${from.address}`) + return + } const fromHeader = mta.message.headers.find((header) => header[0] === 'From')?.[1] if (fromHeader !== undefined) { from.name = extractContactName(fromHeader) diff --git a/services/mail/pod-inbound-mail/src/message.ts b/services/mail/pod-inbound-mail/src/message.ts index 72cee10b8c..8e2287daec 100644 --- a/services/mail/pod-inbound-mail/src/message.ts +++ b/services/mail/pod-inbound-mail/src/message.ts @@ -18,8 +18,8 @@ import { type Ref, type TxOperations, generateId, + PersonUuid, RateLimiter, - SocialIdType, systemAccountUuid } from '@hcengineering/core' import { getClient as getAccountClient } from '@hcengineering/account-client' @@ -56,40 +56,40 @@ export async function createMessages ( const transactorUrl = wsInfo.endpoint.replace('ws://', 'http://').replace('wss://', 'https://') const client = await createRestTxOperations(transactorUrl, wsInfo.workspace, wsInfo.token) - const fromPersonId = await ensureGlobalPerson(accountClient, mailId, from) - if (fromPersonId === undefined) { + const fromPerson = await ensureGlobalPerson(accountClient, mailId, from) + if (fromPerson === undefined) { console.error(`[${mailId}] Unable to create message without a proper FROM`) return } - const toPersons: { address: string, socialId: PersonId }[] = [] + const toPersons: { address: string, uuid: PersonUuid, socialId: PersonId }[] = [] for (const to of tos) { - const toPersonId = await ensureGlobalPerson(accountClient, mailId, to) - if (toPersonId === undefined) { + const toPerson = await ensureGlobalPerson(accountClient, mailId, to) + if (toPerson === undefined) { continue } - toPersons.push({ address: to.address, socialId: toPersonId }) + toPersons.push({ address: to.address, ...toPerson }) } if (toPersons.length === 0) { console.error(`[${mailId}] Unable to create message without a proper TO`) return } - const modifiedBy = fromPersonId - const participants = [fromPersonId, ...toPersons.map((p) => p.socialId)] + const modifiedBy = fromPerson.socialId + const participants = [fromPerson.socialId, ...toPersons.map((p) => p.socialId)] try { - const spaces = await getPersonSpaces(client, mailId, fromPersonId, from.address) + const spaces = await getPersonSpaces(client, mailId, fromPerson.uuid, from.address) if (spaces.length > 0) { await saveMessageToSpaces(client, mailId, spaces, participants, modifiedBy, subject, content, inReplyTo) } } catch (err) { - console.error(`[${mailId}] Failed to save message to personal spaces of ${fromPersonId} (${from.address})`, err) + console.error(`[${mailId}] Failed to save message to personal spaces of ${fromPerson.uuid} (${from.address})`, err) } for (const to of toPersons) { try { - const spaces = await getPersonSpaces(client, mailId, to.socialId, to.address) + const spaces = await getPersonSpaces(client, mailId, to.uuid, to.address) if (spaces.length > 0) { await saveMessageToSpaces(client, mailId, spaces, participants, modifiedBy, subject, content, inReplyTo) } @@ -102,14 +102,14 @@ export async function createMessages ( async function getPersonSpaces ( client: TxOperations, mailId: string, - personId: PersonId, + personUuid: PersonUuid, email: string ): Promise { - const socialIdents = await client.findAll(contact.class.SocialIdentity, { type: SocialIdType.EMAIL, value: email }) - const personRefs = socialIdents.map((socialId) => socialId.attachedTo) + const persons = await client.findAll(contact.class.Person, { personUuid }, { projection: { _id: 1 } }) + const personRefs = persons.map((p) => p._id) const spaces = await client.findAll(contact.class.PersonSpace, { person: { $in: personRefs } }) if (spaces.length === 0) { - console.log(`[${mailId}] No personal space found for ${personId} (${email}), skip`) + console.log(`[${mailId}] No personal space found for ${personUuid} (${email}), skip`) } return spaces } diff --git a/services/mail/pod-inbound-mail/src/person.ts b/services/mail/pod-inbound-mail/src/person.ts index 0132f59944..29967f5699 100644 --- a/services/mail/pod-inbound-mail/src/person.ts +++ b/services/mail/pod-inbound-mail/src/person.ts @@ -20,17 +20,18 @@ export async function ensureGlobalPerson ( client: AccountClient, mailId: string, contact: { address: string, name: string } -): Promise { +): Promise<{ socialId: PersonId, uuid: PersonUuid } | undefined> { const socialKey = buildSocialIdString({ type: SocialIdType.EMAIL, value: contact.address }) - const personId = await client.findSocialIdBySocialKey(socialKey) - if (personId !== undefined) { - console.log(`[${mailId}] Found global person for ${contact.address}: ${personId}`) - return personId + const socialId = await client.findSocialIdBySocialKey(socialKey) + const uuid = await client.findPersonBySocialKey(socialKey) + if (socialId !== undefined && uuid !== undefined) { + console.log(`[${mailId}] Found global person for ${contact.address}: ${uuid}`) + return { socialId, uuid } } const [firstName, lastName] = contact.name.split(' ') try { const globalPerson = await client.ensurePerson(SocialIdType.EMAIL, contact.address, firstName, lastName) - return globalPerson.socialId + return globalPerson } catch (err) { console.error(`[${mailId}] Failed to create global person for ${contact.address}`, err) }