Store the commercial Mail.dll license alongside the infrastructure project. The file is not referenced by the csproj, so it is not copied to build output automatically.
Record.Exception does not observe faults from an async method. Convert the affected tests to async Task and use Record.ExceptionAsync so publish failures are actually asserted.
Await ISendingEmailPublisher.EnqueueAsync so publish failures surface to the caller instead of being lost in a fire-and-forget call.
BREAKING CHANGE: EmailSender.Send now returns Task and must be awaited. Synchronous callers that relied on exceptions being thrown directly from Send will no longer observe them.
Make the client package self-contained:
- Set IsPackable and keep project references private
- Add direct Application and Domain references needed at compile time
- Add EmbedProjectReferences target so referenced assemblies ship inside the package
- Reference System.Text.Json for .NET Framework targets
- Reference Options.ConfigurationExtensions explicitly
- Bump package version to 1.0.5
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.