Replaced the `AsyncInitWorker` background service with the new `ConsumerInitWorker`, which introduces enhanced error handling, logging, and configurability for RabbitMQ consumer initialization.
Updated `MessagingServiceDbContext` to remove the `UseCollation` configuration for the `Username` property in the `EmailAccount` entity, ensuring compatibility with the InMemory database.
Added the `ContinueOnInitFailure` property to `RabbitMqConfiguration` to allow the application to continue running if RabbitMQ consumer initialization fails.
Cleaned up unused `using` directives in `DependencyInjection.cs` and removed the obsolete `AsyncInitWorker` class.
The `IEncryptionService` interface and its implementation,
`DataProtectionEncryptionService`, have been removed from the
codebase. These components previously provided encryption and
decryption functionality using the ASP.NET Core Data Protection API.
Additionally, the dependency injection setup for the encryption
service and the Data Protection API configuration (e.g., key
persistence and application name) have been removed from
`DependencyInjection.cs`.
Replaced `Directory.GetCurrentDirectory()` with `AppContext.BaseDirectory` in `Program.cs` to set the base path for configuration loading. This ensures configuration files are loaded relative to the application's runtime location instead of the current working directory.
Consolidated email fetching queries into a unified `ReadEmailQuery` to support multiple protocols (IMAP, IMAP OAuth2, POP3) dynamically. Removed redundant query handlers (`ReadEmailViaImapQuery`, `ReadEmailViaOAuth2Query`, `ReadEmailViaPop3Query`) and merged their functionality into `ReadEmailQueryHandler` with protocol-specific methods.
Updated `FetchEmailsQueryValidator` to validate the new query. Refactored `EmailController` to use the unified query, simplifying endpoints and consolidating functionality. Removed obsolete endpoints for POP3 and OAuth2 fetching.
Performed code cleanup, including removing redundant imports and consolidating attachment handling logic. Updated project version to `2.0.0-beta` to reflect these significant changes. Improved documentation to align with the new structure.
Updated ReadEmailQuery to return a new response type,
ReadEmailQueryResponse, which includes both email data
and metadata (e.g., LastSync). Added the Account property
to ReadEmailQuery for specifying the email account.
Refactored ReadEmailQueryHandler to:
- Use IImapEmailService to fetch LastSync metadata.
- Return ReadEmailQueryResponse instead of a collection
of ReceivedEmailDto.
Introduced ReadEmailQueryResponse class to encapsulate
LastSync and Emails properties.
Updated EmailController to handle the new response
structure, ensuring compatibility with the updated
ReadEmailQuery and its handler.
Replaced `IMemoryCache` with a thread-safe `ConcurrentDictionary`
for managing IMAP sync dates in `LimilabsImapEmailService`. Added
`GetLastImapSyncDate` and `SetLastImapSyncDate` methods to handle
cache operations. Updated the `IImapEmailService` interface to
include `GetLastImapSyncDate`. Simplified the `MarkAsSeenAsync`
method signature for better readability. Introduced a private
record type `ImapCacheKey` to encapsulate cache keys.
Replaced `FetchEmailsAsync` with `SyncEmailsAsync` in `IImapEmailService` to simplify email synchronization. Updated method signatures to use `DateFilter` and added default parameters for `folder` and `cancel`.
Refactored `LimilabsImapEmailService` to remove client-side filtering logic and delegate storage to `IRepository<ReceivedEmail>`. Simplified IMAP search criteria to focus on date-based filtering and added checks to skip already-synced emails.
Updated `EmailSyncWorker` to use the new `SyncEmailsAsync` method. Removed unused code, streamlined exception handling, and improved maintainability by reducing complexity and focusing on server-side filtering.
Replaced `IMailRepository` with `IReceivedEmailRepository` to improve modularity and functionality. Updated `IReceivedEmailRepository` to make the `EmailAccount` parameter optional in the `FindAsync` method.
Added `ReceivedEmailRepository` with advanced filtering capabilities, including account, flags, text, UID, date, and recipient filters. Implemented deferred materialization for recipient filtering due to EF Core limitations.
Registered `IReceivedEmailRepository` in dependency injection. Updated `ReadEmailQueryHandler` to use the new repository. Improved query performance by applying filters conditionally.
Renamed the `IMailRepository` interface to `IReceivedEmailRepository`
to better reflect its purpose. Added a new `FindAsync` method to
the interface, which supports searching for received emails using
a `MailSearchFilter`, an `EmailAccount`, and an optional
`CancellationToken`. The method returns a `Task` resolving to
an `IEnumerable<ReceivedEmail>`.
Renamed `_dbSet` to `DbSet` and changed its accessibility from
`private` to `protected` to allow access in derived classes.
Updated all methods in the `Repository` class to use the new
`DbSet` field for querying, adding, updating, and removing
entities. This includes methods like `CreateAsync`,
`GetByIdAsync`, `FindAsync`, `UpsertAsync`, `UpdateAsync`,
and `DeleteAsync`.
Improved code consistency and readability by removing
redundant `_dbSet` references and standardizing on the
`DbSet` field.
Introduced a new `IMailRepository` interface to abstract email-fetching logic, replacing the direct dependency on `IImapEmailService` in `ReadEmailQueryHandler`. Updated `ReadEmailQueryHandler` to use `IMailRepository` for querying emails and added `IMapper` for mapping entities to DTOs.
Modified the constructor of `ReadEmailQueryHandler` to inject `IMailRepository`, `IMapper`, and renamed `IRepository<EmailAccount>` to `EmailAccountRepo`. Replaced `IImapEmailService.FetchEmailsAsync` with `IMailRepository.FindAsync` in the handler's `Handle` method.
Wrapped all changes in `#if NET` preprocessor directives to ensure compatibility with specific build configurations. These changes improve modularity, testability, and separation of concerns.
Renamed `FetchEmailsQuery` to `ReadEmailQuery` across the codebase, including its handler, validator, and usages in `EmailController`. Updated method signatures, dependencies, and XML documentation to reflect the new naming convention. Adjusted `ILogger` dependency in the handler to match the renamed class.
Simplified the `LimilabsImapEmailService` by removing the dependency on `IMemoryCache` and eliminating all caching logic. The constructor no longer accepts an `IMemoryCache` parameter, and the static `CacheKeyPrefix` field has been removed.
Replaced the caching mechanism with direct email fetching using `imap.GetMessageByUIDAsync`. Refactored the logic for processing attachments and visuals into `EmailAttachmentDto` objects, and streamlined the construction of `ReceivedEmailDto` to include metadata directly from the fetched email data.
These changes reduce complexity, improve maintainability, and ensure the service always retrieves the latest email data from the IMAP server.
- ExceptionHandlingMiddleware: map BadRequestException to 400 Bad Request response
- Add EmailAccountController: GET /email-accounts (with optional Id/Username filter),
POST/PUT/DELETE via EmailAccountModificationCommand for full CRUD over email accounts
- EmailSyncWorker now fetches active email accounts from IRepository<EmailAccount>
on every polling cycle instead of reading from static options list
- Add UpsertSeedEmailAccount: on startup, seed accounts from EmailAccountsOptions
into the database via IRepository.UpsertAsync (insert or update by Username)
- Remove standalone EmailAccountSyncWorker (merged into EmailSyncWorker)
- FetchEmailsQuery, MarkEmailAsSeenCommand, PublishEmailCommand: resolve EmailAccount
via IRepository<EmailAccount> instead of dispatching GetEmailAccountQuery through ISender
- Swap InvalidOperationException for BadRequestException when IMAP server is not configured
- Add ILogger to handlers; warn when multiple accounts match the lookup criteria
- EmailAccountsOptions.Accounts now typed as IEnumerable<EmailAccountModificationDto>
instead of IEnumerable<EmailAccount> to decouple config from domain entity
- EmailMappingProfile: add EmailAccount <-> EmailAccountDto/EmailAccountModificationDto maps