Wire the infrastructure health checks into ASP.NET Core:
- /health returns JSON via UIResponseWriter and maps Unhealthy to HTTP 503
- /health-ui renders a Razor Pages dashboard with per-check status, description, tags and duration
- Tag health checks (rabbitmq, workers, ready, live) for monitoring filters
- Link the dashboard from the Swagger description and the page layout
ConsumerInitWorker marks ConsumerInitHealthCheck as unhealthy when the consumer pool fails to start, so callers receive HTTP 503 instead of a silently degraded service.
EmailSyncWorker now reports its startup interval and the result of every sync cycle. SyncAccountAsync returns whether the account failed, letting the worker count errors per cycle and expose them through EmailSyncWorkerHealthCheck.
Introduce singleton health checks that background workers update at runtime:
- ConsumerInitHealthCheck reports whether the RabbitMQ consumer pool started
- RabbitMqConnectionHealthCheck opens a channel to verify broker reachability
- EmailSyncWorkerHealthCheck detects stalled or erroring sync cycles
Register all three in the infrastructure DI container so the API layer can wire them into the health check pipeline.
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.