Commit graph

15 commits

Author SHA1 Message Date
map
5293be6a4a
Implement spam training data sync and add TutanotaModelV98
We sync the spam training data encrypted through our server to make
sure that all clients for a specific user behave the same when
classifying mails. Additionally, this enables the spam classification
in the webApp. We compress the training data vectors
(see clientSpamTrainingDatum) before uploading to our server using
SparseVectorCompressor.ts. When a user has the ClientSpamClassification
enabled, the spam training data sync will happen for every mail
received.

ClientSpamTrainingDatum are not stored in the CacheStorage.
No entityEvents are emitted for this type.
However, we retrieve creations and updates for ClientSpamTrainingData
through the modifiedClientSpamTrainingDataIndex.

We calculate a threshold per classifier based on the dataset ham to spam
ratio, we also subsample our training data to cap the ham to spam ratio
within a certain limit.

Co-authored-by: jomapp <17314077+jomapp@users.noreply.github.com>
Co-authored-by: das <das@tutao.de>
Co-authored-by: abp <abp@tutao.de>
Co-authored-by: Kinan <104761667+kibibytium@users.noreply.github.com>
Co-authored-by: sug <sug@tutao.de>
Co-authored-by: nif <nif@tutao.de>
Co-authored-by: map <mpfau@users.noreply.github.com>
2025-11-18 13:56:19 +01:00
sug
f11e59672e
improve inbox rule handling and run spam prediction after inbox rules
Instead of applying inbox rules based on the unread mail state in the
inbox folder, we introduce the new ProcessingState enum on
the mail type. If a mail has been processed by the leader client, which
is checking for matching inbox rules, the ProcessingState is
updated. If there is a matching rule the flag is updated through the
MoveMailService, if there is no matching rule, the flag is updated
using the ClientClassifierResultService. Both requests are
throttled / debounced. After processing inbox rules, spam prediction
is conducted for mails that have not yet been moved by an inbox rule.
The ProcessingState for not matching ham mails is also updated using
the ClientClassifierResultService.

This new inbox rule handing solves the following two problems:
 - when clicking on a notification it could still happen,
   that sometimes the inbox rules where not applied
 - when the inbox folder had a lot of unread mails, the loading time did
   massively increase, since inbox rules were re-applied on every load

Co-authored-by: amm <amm@tutao.de>
Co-authored-by: Nick <nif@tutao.de>
Co-authored-by: das <das@tutao.de>
Co-authored-by: abp <abp@tutao.de>
Co-authored-by: jhm <17314077+jomapp@users.noreply.github.com>
Co-authored-by: map <mpfau@users.noreply.github.com>
Co-authored-by: Kinan <104761667+kibibytium@users.noreply.github.com>
2025-10-22 09:40:45 +02:00
ivk
83a81c31b8 Fix incorrect imports from @tutao/tutanota-utils 2025-09-30 16:40:14 +02:00
yoy
2675f20c74 feat(theme): Update theme colors
- Introduce the new colors for all color themes
- The colors are based on the Material 3 color but customized
2025-09-26 14:15:49 +02:00
hrb-hub
33f4432484 Fix base64url.replace is not a function error when reactivating alias
The error is a result of an incorrect assumption that EntityUpdateData's
instanceListId is null for ElementEntities when processing entity
updates, when in fact instanceListId is an empty string.

Changing EntityUpdateData.instanceListId's type to NonEmptyString | null
and setting it to null for ElementEntity updates early should help
prevent bugs caused by such assumptions.

Close #9420

Co-authored-by: bir <bir@tutao.de>
Co-authored-by: ivk <ivk@tutao.de>
2025-08-29 10:26:11 +02:00
jhm
5e8aa2bf05
introduce PrefetchStatus in entityUpdateData
We introduce a PrefetchStatus to account for instances not returned
by the server as early as possible. This ensures that we do not throw
in case of 404 not found or 403 not authorized error, when instances
corresponding to create or update entityUpdates have already been
deleted or permissions have been revoked.

Co-authored-by: abp <abp@tutao.de>
2025-07-04 14:14:32 +02:00
abp
4db7e9b1e9
add prefetching to missed entityUpdates, instance/patch on EntityUpdate
When processing the missed entityUpdates in EventQueue in EventBusClient
, we group entityUpdates based on typeRefs and listIds and do
loadMultiple requests instead of loading them one-by-one (prefetching).
Additionally, when the client is online, the server enriches the
WebSocket message with either the instance (in case of a CREATE event),
or with the patches list (in case of an UPDATE event) so that we do not
need to do an additional GET request and can either put the instance
into the cache or update the entry on the cache using the PatchMerger
instead.

Co-authored-by: abp <abp@tutao.de>
Co-authored-by: das <das@tutao.de>
Co-authored-by: jomapp <17314077+jomapp@users.noreply.github.com>
Co-authored-by: Kinan <104761667+kibibytium@users.noreply.github.com>
Co-authored-by: map <mpfau@users.noreply.github.com>
Co-authored-by: sug <sug@tutao.de>
2025-07-02 14:00:11 +02:00
wrd
5cd3392d43 Reimplement search filters using Chips
#9010

Co-authored-by: wrd <wrd@tutao.de>
2025-06-04 10:38:22 +02:00
ivk
86d5775e16 Add SQLite search on clients where offline storage is available
- Introduce a separate Indexer for SQLite using FTS5
- Split search backends and use the right one based on client (IndexedDB
  for Browser, and OfflineStorage everywhere else)
- Split SearchFacade into two implementations
- Adds a table for storing unindexed metadata for mails
- Escape special character for SQLite search
  To escape special characters from fts5 syntax. However, simply
  surrounding each token in quotes is sufficient to do this.
  See section 3.1 "FTS5 Strings" here: https://www.sqlite.org/fts5.html
  which states that a string may be specified by surrounding it in
  quotes, and that special string requirements only exist for strings
  that are not in quotes.
- Add EncryptedDbWrapper
- Simplify out of sync logic in IndexedDbIndexer
- Fix deadlock when initializing IndexedDbIndexer
- Cleanup indexedDb index when migrating to offline storage index
- Pass contactSuggestionFacade to IndexedDbSearchFacade
    The only suggestion facade used by IndexedDbSearchFacade was the
    contact suggestion facade. So we made it clearer.
- Remove IndexerCore stats
- Split custom cache handlers into separate files
  We were already doing this with user, so we should do this with the
  other entity types.

- Rewrite IndexedDb tests
- Add OfflineStorage indexer tests
- Add custom cache handlers tests to OfflineStorageTest
- Add tests for custom cache handlers with ephemeral storage
- Use dbStub instead of dbMock in IndexedDbIndexerTest
- Replace spy with testdouble in IndexedDbIndexerTest

Close #8550

Co-authored-by: ivk <ivk@tutao.de>
Co-authored-by: paw <paw-hub@users.noreply.github.com>
Co-authored-by: wrd <wrd@tutao.de>
Co-authored-by: bir <bir@tutao.de>
Co-authored-by: hrb-hub <hrb-hub@users.noreply.github.com>
2025-06-04 10:36:46 +02:00
wrd
f6552c6c55 Try to apply inbox rule on mail that was loaded through notification
Emails opened through notification would be marked as read before the
inbox rules would apply and this would cause inbox rules to not be
applied.

We changed it by forcibly applying inbox rules to the emails opened
from notifications.

Close #8393
2025-06-04 10:36:46 +02:00
ivk
9e31ee0409 Inject type model resolvers
Passing instances explicitly avoids the situations where some of them
might not be initialized.

We also simplified the entity handling by converting entity updates to
data with resolved types early so that the listening code doesn't have
to deal with it.

We did fix some of the bad test practices, e.g. setting/restoring env
incorrectly. This matters now because accessors for type model
initializers check env.mode.

Co-authored-by: paw <paw-hub@users.noreply.github.com>
2025-05-27 14:52:44 +02:00
Kinan
edbf281b88
switch to typeIds and attrIds, add SystemMV126, TutanotaMV86, BaseMV2
Refactor our instance deserialization/serialization pipeline, both on
TypeScript and on Rust [sdk] to use typeId and attributeIds instead of
typeNames and attributeNames. We furthermore ignore cardinalities
on associations until the instance layer and always
store associations as arrays. This commit introduces **eventual
consistency** on the client, i.e. we are from now on always storing data
in the newest schema format (activeApplicationVersionsForWritingSum)
which ensures that all data is already available on the client after
updating the client to a newer version. This removes the need for
offline migrations on the client and also removes backward migrations
on the server. Furthermore, the server model types are now available
on the client, retrievable through the ApplicationTypesFacade. This is
our first step towards FastSync.

Co-authored-by: nig <nig@tutao.de>
Co-authored-by: abp <abp@tutao.de>
Co-authored-by: jomapp <17314077+jomapp@users.noreply.github.com>
Co-authored-by: map <mpfau@users.noreply.github.com>
Co-authored-by: sug <sug@tutao.de>
Co-authored-by: Kinan <104761667+kibibytium@users.noreply.github.com>
2025-04-28 12:44:35 +02:00
paw
0321b53e3e Add ConversationListModel
- This list model groups all emails by conversation in the mail list
- Also adds setting for grouping by conversation (i.e. enables this)
- The setting is overridden for SENT and DRAFT folder types (it uses the
  other per-mail list model instead)
- Adds MailSetListModel which provides a common interface for the
  MailViewModel so that additional list models can be created; it is
  used for MailListModel and the new ConversationListModel, but it can
  be extended to even more list models in the future if it is ever
  desired.

Note: This does not include actions. Any action you do (delete, archive,
etc.) will be applied to the selected email. The purpose of this commit
is to just implement the list model. See #5051 for more information.

Closes #8223

Co-authored-by: bir <bir@tutao.de>
Co-authored-by: ivk <ivk@tutao.de>
2025-03-05 16:26:09 +01:00
abp
84d4c125f0
remove legacy MailFolders and add TutanotaModelV83
Co-authored-by: jhm <17314077+jomapp@users.noreply.github.com>
2025-02-11 16:53:52 +01:00
paw
8727eec53c Add tests for MailListModel, fix loadAndSelect
These were missing from MailViewModel, so they weren't required when the
code was refactored into MailListModel. However, we still want this code
tested as it has a lot of complex logic, especially regarding entity
updates.

Also fixes a few bugs with MailListModel that were found, particularly
with loadAndSelect. We can also remove one usage of loadAndSelect as
we can synchronously select an element, too, without any loading.

Closes #8340

Co-authored-by: bir <bir@tutao.de>
2025-01-24 13:54:57 +01:00