Commit Graph

95 Commits

Author SHA1 Message Date
Félix Malfait e577c2d746 Update user friendly errors for translations (#15000)
Force msg typing instead of string for user friendly errors
2025-10-09 18:17:32 +02:00
neo773 62a1de221b Message Folders Redesign and Import Policy (#14714) 2025-10-01 14:48:46 +02:00
neo773 6f49481095 Imap perf improvement (#14629)
- Removed buffer to string conversion on message and we instead pass the
direct Buffer
- Removed redundant flattening of results
- Cached `JSDOM` and `DOMPurify` Instance
- MailParser added `skipTextToHtml` along with some other options, which
reduced parsing time from 50ms to 35ms

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-09-23 09:21:30 +02:00
Charles Bochet 349b15e81f Add scripts to relaunch message and calendar channels (#14579)
## Context

1. We are debugging the experience on messaging and calendar sync. I'm
adding two scripts to relaunch messaging and calendar channels
2. We are seeing errors in Sentry regarding microsoft drivers errors. I
was about to fix them but I'm refactoring / simplifying a bit the logic
first. It will be a betters starting point
2025-09-19 12:31:19 +02:00
Charles Bochet f9677122b6 Improve Messaging Gmail experience (#14342)
In this PR, I'm solving several issues:
1) We were not checking if the currentWorkspaceMember was owning the
message in the thread. It kind of worked before because the case of
shared threads (with shared threads visibility restriction) was not
happening that often. It seems that the bug has always been there
2) Re-implement orphan messages and threads deletion on messageChannel
deletion. We used to brutally look for all orphans, we disabled it last
week because it was too heavy on db. I've re-implemented it more
carefully and "surgically"
3) Gmail sync was not handling folder synced correctly. It was
leveraging labelIds which it shouldn't do (this is a AND AND parameter)
in full sync
4) Added a command to clean orphan message threads manually if needed.
Usually this is done when you remove a messageChannel, or change
blocklist rules but it can be useful to have it to debug
2025-09-07 20:36:28 +02:00
neo773 8ab71fef1f feat: message folders control (#14144)
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-08-30 17:39:10 +02:00
neo773 6eb9a4e024 Smtp username (#14134)
Tested with vendor resend.com

/closes #14120
2025-08-28 14:49:39 +02:00
Weiko 533d7fe49a Deprecate legacy core datasource token (#14096) 2025-08-27 20:09:54 +02:00
neo773 0c8631c1c8 Update sent folder regex (#14069) 2025-08-25 17:47:31 +02:00
neo773 734b0bd2d2 IMAP Refactor (#14053)
- Removed `IMAPMessageLocator` service which relied on `Message-ID`
header lookups.

We now fetch messages directly by UID, which should eliminate most of
the issues we were hitting.

This had a challenge, `messageIdsToFetch` were flattened and UIDs are
only unique within their own folder.
To preserve context without modifying the core message module, I landed
on using composite keys for IMAP message IDs.

Each UID is now prefixed with its folder name, and we parse it back when
needed to recover the folder.
This feels like a reasonable trade-off since it resolves a lot of the
failures we saw with `Message-ID` lookups.

  And Syncs are faster now since there's no double scanning.

- Added `QRESYNC` support for servers that provide it, giving us faster
incremental sync.

- Refactored code to better split concerns.  

### Compatibility Test

| Server              | Status     |
|---------------------|------------|
| Gmail               |  Tested  |
| Dovecot             |  Tested  |
| Stalwart            |  Tested  |
| Titan Email  |  Tested  |
| FastMail  |  Tested  |

<img width="804" height="418" alt="image"
src="https://github.com/user-attachments/assets/b414a484-2798-4839-b395-9dd5c153effe"
/>
2025-08-25 16:42:07 +02:00
neo773 44916afcdd fix extract-message-util preserve line break for multi line HTML text (#13983)
Upon more testing with titan email I found emails with multi line text
did not preserve line break in HTML, this fixes it.
2025-08-20 07:49:05 +02:00
neo773 c582666aeb IMAP FIxes (#13973)
- Added `ImapFindSentMailboxService` to replace utility function it
fixes an edge case where special flag `Sent` folder may have zero
messages, we fall back to regex based approach to find other candidates
- Fixed edge case where some servers may not return text content for
body it parses the HTML in that case
- Some other enhancements with capability based detection

Tested with Stalwart server and Titan email

/closes #13884
2025-08-19 19:22:13 +02:00
Charles Bochet b14063fe06 Re-add prettier (#13812)
Re add prettier in eslint.configs
2025-08-11 14:10:04 +02:00
Félix Malfait 464a480043 Continue ESLINT9 Migration (#13795)
Might already fix #13793
2025-08-10 23:25:58 +02:00
Charles Bochet b55c46f4a3 Few fixes before release 1.3.0 (#13791) 2025-08-09 03:08:11 +02:00
Félix Malfait 0236f79ccf Fix assert unreachable, remove unused variables (#13753)
Small code cleanup
2025-08-08 09:04:45 +02:00
Félix Malfait 8b4b9ef8da Change type import rule (#13751)
Forcing "type" to be explicit, works best will rollup on the frontend to
exclude depdendencies
2025-08-08 01:27:05 +02:00
neo773 9ceb097ab7 IMAP Fixes & Improvements (#13582)
- Removed caching of IMAP client as it was problematic and didn't really
matter because of our pipeline, also added retry logic to client.
- Some code refactoring and cleanup
- Breaking changes:
   - Removed messageChannel.syncCursor
   - Uses messageFolder.syncCursor instead
- Removed Date based sync cursor in favor of message UID which is much
more reliable and precise

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-08-05 09:46:28 +02:00
Charles Bochet 2eeddcddc6 Add TwentyORM query read timeout exception (#13603)
In this PR:
- adding a try / catch around all ORM internal methods save, insert,
upsert, findOne, ...
- leveraging this error to prevent messageChannels to get FAILED
- optimizing messaging BATCH_SIZE and THROTTLE threshold according to
local tests
- 

<img width="1510" height="851" alt="image"
src="https://github.com/user-attachments/assets/802fd933-caac-4291-9cde-34a1ddf59c06"
/>
2025-08-04 17:16:16 +02:00
Charles Bochet dc3c194f3e Improve messaging sync performances (#13549)
This PR aims to improve performances as we are making A LOT of queries
after having added events emission to the ORM layer. While investigating
issues, I've come across multiple problems I will describe below

## Add index on workspace.activationStatus as we are querying it a lot

As per title

## Add logs on core datasource destroy

It seems that we have postgres connection pool destruction in
production. I cannot reproduce locally but I suspect the Query Timeouts
to be the root cause. I'm fixing most of the Query Timeouts cause in
this PR but I'm adding the logs so we have more information in case in
keeps happening in production.

## GraphQL query runner createMany

It was using a for loop on each record. This is as issue has we will
emit an event separately for each record => we should always try to
batch events.
Replacing by a save on all records. Note that this is not perfect as we
should avoid using save (bad performances), and use insert + updateMany
instead. As I have follow up discussions regarding permissions, I
haven't replaced it by insert and updateMany yet. Using save instead of
a for loop makes the problem less worrying.

## Introduce updateMany in ORM @Weiko @ijreilly FYI

.save(manyRecords) is bad as it's querying the data for no good reason
(and doing a select for each record...).
We already have .insert(), i'm introducing .updateMany()

I think our ORM layer should be simplified a lot but I'm not starting
the refacto yet

## Fixing ORM @Weiko @ijreilly  FYI
- Fixing events emission in delete function
- Fixing events emission in insert function
- make sure everything is batched

## Events performance @Weiko @ijreilly FYI

Do not emit timelineActivity db events as this does not seem useful and
is quite heavy

## Messaging and Calendar performance @bosiraphael FYI

Rework many functions to make sure they are batched. This does not touch
the driver layer and I have heavily tested it. (multiple account, with
multiple channels, common thread, common messages, etc...)

## Workflow Trigger relation Fetch performance @martmull FYI

Improved performance by batching
2025-08-03 23:56:44 +02:00
Antoine Moreaux 23353e31e6 feat(domain-manager): refactor custom domain validation and improve c… (#13388) 2025-08-01 09:01:27 +02:00
neo773 0e4e3acaba fix: IMAP Import (#13500)
/closes #13397
2025-07-30 15:08:00 +02:00
neo773 c769f9f2d2 fix: invalid byte sequence for encoding (#13387)
/closes #13366

cc
@FelixMalfait
2025-07-23 18:15:08 +02:00
Charles Bochet 8b5eb04b07 Refactor mail folders (#13302)
## Context

We would like to start leveraging more messageFolders during messageSync
which would allow users to select folders they want to sync on their
mailbox. MessageFolder is an abstraction that means folder for
Microsoft, labels for Gmail, not supported for IMAP.


## What

1) We do not aim to build a FE now but we would like to take it into a
consideration if they have been modified through API. So **out of
scope**
2) MessageFolders will be synced regularly from Gmail, Microsoft. This
is currently partially done and improving it is **out of scope**
3) Change: we were having two synchronization mechanism so far:
FULL_SYNC (first time, or when no cursor is present) and PARTIAL_SYNC
(when we have a cursor, we can fetch the diff since the last pull). This
Full vs Partial mode was a high level concept. We now think it's an
driver implementation detail (and can be inferred from the existence of
a cursor). Why making this change now: as we are trying to pull several
folders, a folder could need a full sync if it had no cursor, and
another a partial if it has one. It does not make sense anymore to have
this full vs partial difference at MessageChannel level
4) Once we are sure this work, we can start syncing different folders on
Gmail side (the case for the user it to be able to fetch Promotion
label)

## Implementation strategy

1) Re-use PartialMessageList implementation / API and rename it to
MessageList at it's more complete
2) re-use driver level fullMessageList methods and call them
messageListWithoutCursor
3) make sure that these method are folder specific

## Tests

### Gmail

- Fresh fetch (without cursor): OK
- Message import: OK
- Additional fetch (with messageChannel cursor): OK

### Microsoft

- Fresh fetch (without cursor): OK
- Message import: OK
- Additional fetch (with messageChannel cursor): OK

### Imap

- Fresh fetch (without cursor): OK
- Message import: OK
- Additional fetch (with messageChannel cursor): OK
2025-07-22 11:20:57 +02:00
Weiko 2deac9448e Add db event emitter in twenty orm (#13167)
## Context
Add an eventEmitter instance to twenty datasources so we can emit DB
events.
Add input and output formatting to twenty orm (formatData, formatResult)
Those 2 elements simplified existing logic when we interact with the
ORM, input will be formatted by the ORM so we can directly use
field-like structure instead of column-like. The output will be
formatted, for builder queries it will be in `result.generatedMaps`
where `result.raw` preserves the previous column-like structure.

Important change: We now have an authContext that we can pass when we
get a repository, this will be used for the different events emitted in
the ORM. We also removed the caching for repositories as it was not
scaling well and not necessary imho

Note: An upcoming PR should handle the onDelete: cascade behavior where
we send DESTROY events in cascade when there is an onDelete: CASCADE on
the FK.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-07-17 18:07:28 +02:00
neo773 aede38000e feat: SMTP Driver Integration (#12993)
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-07-10 15:17:26 +02:00
Guillim 8cbb1aa71a Miscrosoft Client errors when refreshing accessToken (#12884)
# Context

We had an error saying "Unknown error importing calendar events for
[...]: Access token is undefined or empty. Please provide a valid token.
For more help -
https://github.com/microsoftgraph/msgraph-sdk-javascript/blob/dev/docs/CustomAuthenticationProvider.md
"

Reason is that the access token method for microsoft is a bit different
than the one from google. And in microsoft case, we want to check the
access token in the authProvider in case it fails. Currently it was not
catched, so it broke services above that counted on the accesstoken to
be valid.

That ended in UNKNOWN failure for our calendar event fetch service.

# Solution

This PR should solve the issue since :
1. forcing the method to break if accesstoken renewal fails
2. logs will help to know what kind of errors will be sent in case we
need to tackle this issue again
3. we now throw TEMPORARY error instead of unknown, allowing 3
getClientConfig failure before it is definitive

Why so many changes while it should have been simple :
The root cause is the `authProvider` from
`'@microsoft/microsoft-graph-client'` npm package. It does not throw a
custom error, and we cannot catch it on calling `Client.init`. Errors
only occurs when the client from
```
const client = this.microsoftOAuth2ClientManagerService.getOAuth2Client(refreshtoken) 
```
is used, as in `client.api('/messages').get().catch(err => [...])`

So we need to go in every call using the client and catch errors, and
rethrow whenver we need as a newly created message type
`MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE`


We discussed 1. and 2. with @bosiraphael already
I added 3. to make our system more robust without waiting for more
failures

# Related

Fixes : https://github.com/twentyhq/twenty/issues/12880

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-07-02 19:03:13 +02:00
neo773 7c8d362772 feat: IMAP Driver Integration (#12576)
### Added IMAP integration 

This PR adds support for connecting email accounts via IMAP protocol,
allowing users to sync their emails without OAuth.

#### DB Changes:
- Added customConnectionParams and connectionType fields to
ConnectedAccountWorkspaceEntity

#### UI:
- Added settings pages for creating and editing IMAP connections with
proper validation and connection testing.
- Implemented reconnection flows for handling permission issues.

#### Backend:
- Built ImapConnectionModule with corresponding resolver and service for
managing IMAP connections.
- Created MessagingIMAPDriverModule to handle IMAP client operations,
message fetching/parsing, and error handling.

#### Dependencies:
Integrated `imapflow` and `mailparser` libraries with their type
definitions to handle the IMAP protocol communication.

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-06-29 21:32:15 +02:00
Guillim 5c3550a2ee in connected account, refresh-token can fail with network error (#12815)
This PR fixes this issue from the connected account refresh token
service that is

This PR fixes error handling in `handleDriverException` by ensuring that
errors resembling `MessageImportDriverException` are correctly detected,
even if they are plain objects and not true class instances. This
prevents missed exception handling due to failed `instanceof` checks.

Was introduced by [this
PR](https://github.com/twentyhq/twenty/pull/12233) that did not know all
provider cases that can occur.

Fixes https://github.com/twentyhq/twenty/issues/12589
2025-06-24 13:51:03 +02:00
Matt Dvertola f60b704feb #12336 adding gmail email sync error handling (#12383)
I believe that some emails with invalid characters are breaking the sync
process.

this PR attempts to create a "safeParseAddress" function. Hopefully this
will change current behavior of a single email breaking the entire sync
process to the sync process "skipping" an invalid email address and
continuing on.

I opened this because of issues explained in #12336

---------

Co-authored-by: guillim <guigloo@msn.com>
2025-06-03 11:17:48 +02:00
Guillim b80a270e9d adding new error codes to the temporary catch (#12366)
For microsoft, examples of errors from the logs:

<img width="1251" alt="Screenshot 2025-05-28 at 18 02 48"
src="https://github.com/user-attachments/assets/7de506b2-3e68-4ee5-907a-62fe6a0e2ba5"
/>


Fixes https://github.com/twentyhq/twenty/issues/12252
2025-06-02 15:15:49 +02:00
Guillim 5914a89df2 Catching temporary errors in microsft batch calls (#12409)
# 🐛 Improve Microsoft Graph API Temporary Error Handling on PARSE method

fixes Sentry error
<img width="886" alt="Screenshot 2025-06-02 at 14 39 19"
src="https://github.com/user-attachments/assets/117a2601-4bad-48a2-8112-2bb682559b15"
/>


### What:
Enhances error handling for Microsoft Graph API batch calls 
### How: by treating HTTP 503 (Service Unavailable) as temporary errors
alongside existing 429 (Rate Limit) handling.

### Additional: 
improving logging


Fixes https://github.com/twentyhq/twenty/issues/12257
2025-06-02 12:46:36 +00:00
Guillim 0a0fb976bf fixing : "message" : "Mail service not enabled" (#12349)
Fix Gmail API error handling for "Mail service not enabled" scenarios
Add proper await

Improves Gmail API error handling by properly detecting "Mail service
not enabled" errors and classifying them as INSUFFICIENT_PERMISSIONS
instead of TEMPORARY_ERROR


Fixes https://github.com/twentyhq/twenty/issues/12260
### Refernce :


https://stackoverflow.com/questions/31692720/gmail-api-returning-status-code-400-error-mail-service-not-enabled
2025-05-28 13:49:19 +02:00
Guillim 6ef9a3b4c9 Empty Gmail box bug (#12225)
if gmail is empty, there is an error. This PR handles this use-case
2025-05-23 17:21:31 +02:00
Guillim 6ff5a5bafa fixing a microsoft graph api error (#12154)
The issue is "Microsoft Graph API unknown error: TypeError: Cannot read
properties of undefined (reading 'emailAddress')"

Sentry :
https://twenty-v7.sentry.io/issues/6605750776/events/7feb4f5949a64ab78bb429cffb7f0fea/?project=4507072499810304

Fixes https://github.com/twentyhq/core-team-issues/issues/981
2025-05-21 11:04:43 +02:00
Guillim 91e487dd63 Catching "no licence" microsoft account (#12143)
Catching "no licence - removed" microsoft message channels. 

Current behabiour 
> ` MessageImportException [Error]: The mailbox is either inactive,
soft-deleted, or is hosted on-premise.`

Goal:
better track errors VS user mistakes

Context: 
A similar logic was already implemented for the calendar channels. I
just replicated it to message channels
2025-05-21 11:04:11 +02:00
Guillim ad136b5246 better logging errors in messages (#12136) 2025-05-20 13:37:24 +02:00
Paul Rastoin 442f8dbe3c [QRQC_2] No implicitAny in twenty-server (#12075)
# Introduction
Following https://github.com/twentyhq/twenty/pull/12068
Related with https://github.com/twentyhq/core-team-issues/issues/975

We're enabling `noImplicitAny` handled few use case manually, added a
`ts-expect-error` to the others, we should plan to handle them in the
future
2025-05-15 18:23:22 +02:00
Paul Rastoin a8423e8503 [QRQC_2] No explicit any in twenty-server (#12068)
# Introduction

Added a no-explicit-any rule to the twenty-server, not applicable to
tests and integration tests folder

Related to https://github.com/twentyhq/core-team-issues/issues/975
Discussed with Charles

## In case of conflicts
Until this is approved I won't rebased and handle conflict, just need to
drop two latest commits and re run the scripts etc

## Legacy
We decided not to handle the existing lint error occurrences and
programmatically ignored them through a disable next line rule comment

## Open question
We might wanna activate the
[no-explicit-any](https://typescript-eslint.io/rules/no-explicit-any/)
`ignoreRestArgs` for our use case ?
```
    ignoreRestArgs?: boolean;
```

---------

Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
2025-05-15 16:26:38 +02:00
Guillim c95c4383b4 Gmail temporary error (#12058)
# Handling Google error

This bug is hard to reproduce so the resolution is based only on the
Sentry logs. There is not definite error code
for this error message. in the documentation.
https://developers.google.com/workspace/gmail/api/guides

This is why i added more 5xx code types in order to be sure we catch
this. In order to refine this later, i added the error code to the
message.

Fixes https://github.com/twentyhq/twenty/issues/12025
2025-05-15 16:12:10 +02:00
Guillim fdc7d6c93c Messaging issues (#12041)
messageImportException
for messaging and calendar
add more context to the Sentry Exceptions

Fixes https://github.com/twentyhq/twenty/issues/11994
2025-05-14 18:37:42 +02:00
nitin a15b87649a Twenty config core implementation (#11595)
closes https://github.com/twentyhq/core-team-issues/issues/760

---------

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
2025-04-26 09:21:59 +02:00
Guillim 95808b06b9 Messaging-logging (#11723)
parseBatchResponse:
we need more logs to understand why we have some empty repsonse in the
body.

For anothe PR:  
~~UNKNOWN_NETWORK_ERROR : moving from handleUnknownException to
handleTemporaryException. This is important since in the logs I saw "The
service is currently unavailable" which makes me think we should handle
this type of error with as temporary~~
2025-04-25 18:01:53 +02:00
martmull 0469aba90b Improve from in send email action (#11581)
## Before
<img width="701" alt="image"
src="https://github.com/user-attachments/assets/77184775-5b06-4777-9276-1338cc457070"
/>

## After
<img width="705" alt="image"
src="https://github.com/user-attachments/assets/9528eb0e-54c3-452c-8297-27796ccc75a1"
/>
2025-04-17 11:34:55 +02:00
nitin bd3ec6d5e3 rename core-module environment to twenty-config (#11445)
closes https://github.com/twentyhq/core-team-issues/issues/759
2025-04-09 14:11:26 +02:00
Guillim d9ac662302 Microsoft Throtling error and wrongly types on our side (#11266) 2025-03-28 16:37:46 +00:00
Guillim 96c61df007 fix MailboxConcurrency And email format without @ (#11133) 2025-03-25 11:40:58 +01:00
Paul Rastoin 9ad8287dbc [REFACTOR] twenty-shared multi barrel and CJS/ESM build with preconstruct (#11083)
# Introduction

In this PR we've migrated `twenty-shared` from a `vite` app
[libary-mode](https://vite.dev/guide/build#library-mode) to a
[preconstruct](https://preconstruct.tools/) "atomic" application ( in
the future would like to introduce preconstruct to handle of all our
atomic dependencies such as `twenty-emails` `twenty-ui` etc it will be
integrated at the monorepo's root directly, would be to invasive in the
first, starting incremental via `twenty-shared`)

For more information regarding the motivations please refer to nor:
- https://github.com/twentyhq/core-team-issues/issues/587
-
https://github.com/twentyhq/core-team-issues/issues/281#issuecomment-2630949682

close https://github.com/twentyhq/core-team-issues/issues/589
close https://github.com/twentyhq/core-team-issues/issues/590

## How to test
In order to ease the review this PR will ship all the codegen at the
very end, the actual meaning full diff is `+2,411 −114`
In order to migrate existing dependent packages to `twenty-shared` multi
barrel new arch you need to run in local:
```sh
yarn tsx packages/twenty-shared/scripts/migrateFromSingleToMultiBarrelImport.ts && \
npx nx run-many -t lint --fix -p twenty-front twenty-ui twenty-server twenty-emails twenty-shared twenty-zapier
```
Note that `migrateFromSingleToMultiBarrelImport` is idempotent, it's atm
included in the PR but should not be merged. ( such as codegen will be
added before merging this script will be removed )

## Misc
- related opened issue preconstruct
https://github.com/preconstruct/preconstruct/issues/617

## Closed related PR
- https://github.com/twentyhq/twenty/pull/11028
- https://github.com/twentyhq/twenty/pull/10993
- https://github.com/twentyhq/twenty/pull/10960

## Upcoming enhancement: ( in others dedicated PRs )
- 1/ refactor generate barrel to export atomic module instead of `*`
- 2/ generate barrel own package with several files and tests
- 3/ Migration twenty-ui the same way
- 4/ Use `preconstruct` at monorepo global level

## Conclusion
As always any suggestions are welcomed !
2025-03-22 19:16:06 +01:00
Charles Bochet b49dc57bbf Microsoft mail sync: make sure that message list fetch is using max batch size (#11095)
Fixes https://github.com/twentyhq/core-team-issues/issues/641
2025-03-21 15:20:39 +01:00
Guillim bab529b138 Fixing unhandled exception for microsoft driver (#10223)
Fixing a difficult bug: an unhandled exception for microsoft driver when
one of the many Microsoft BATCH request failed.
2025-02-14 18:50:53 +01:00