From ee279c407b94e79e7ebf9e008e58f9555ddfdd5b Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 10 Aug 2026 14:22:45 +0200 Subject: [PATCH] Remove HasAttachments filter; enhance FetchEmails response The `MailSearchFilter` class was updated to remove the `HasAttachments` property, simplifying the filtering logic. Corresponding client-side filtering logic in `LimilabsImapEmailService` was also removed. The IMAP search query now defaults to `Expression.All` when no criteria are provided. The `FetchEmails` method in `EmailController` was enhanced with a new optional `firstHtmlBodyOnly` parameter. This allows returning only the HTML body of the first email or a `404 Not Found` response if no emails match the criteria. These changes improve flexibility and simplify the codebase. --- .../Common/Models/MailSearch/MailSearchFilter.cs | 6 ------ .../Services/LimilabsImapEmailService.cs | 7 ++----- .../Controllers/EmailController.cs | 9 ++++++++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/core/DigitalData.MessagingService.Application/Common/Models/MailSearch/MailSearchFilter.cs b/src/core/DigitalData.MessagingService.Application/Common/Models/MailSearch/MailSearchFilter.cs index 70e31a6..f0fc2f3 100644 --- a/src/core/DigitalData.MessagingService.Application/Common/Models/MailSearch/MailSearchFilter.cs +++ b/src/core/DigitalData.MessagingService.Application/Common/Models/MailSearch/MailSearchFilter.cs @@ -19,12 +19,6 @@ public record MailSearchFilter /// public bool UnseenOnly { get; init; } = false; - /// - /// When , only messages that carry at least one attachment are returned. - /// Filtered client-side after fetching the message envelope; does not affect the IMAP SEARCH query. - /// - public bool HasAttachments { get; init; } = false; - /// /// When , attachment data is included in the results; otherwise attachments are omitted. /// Defaults to . diff --git a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs index 6fec386..188d439 100644 --- a/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs +++ b/src/infrastructure/DigitalData.MessagingService.Infrastructure/Services/LimilabsImapEmailService.cs @@ -78,7 +78,8 @@ public class LimilabsImapEmailService( } // Get UIDs to fetch - List uids = [.. await imap.SearchAsync(Expression.And([.. criterions]), cancellationToken)]; + var searchExpression = criterions.Count > 0 ? Expression.And([.. criterions]) : Expression.All(); + List uids = [.. await imap.SearchAsync(searchExpression, cancellationToken)]; // Apply requested sort order if (filter.SortOrder == MailSortOrder.NewestFirst) @@ -99,10 +100,6 @@ public class LimilabsImapEmailService( var mail = new MailBuilder().CreateFromEml(eml); var flags = await imap.GetFlagsByUIDAsync(uid, cancellationToken); - // Client-side attachment filter — IMAP has no native criterion for this - if (filter.HasAttachments && mail.Attachments.Count == 0 && mail.Visuals.Count == 0) - continue; - results.Add(MapToContext(uid, mail, flags, filter.WithAttachments)); } catch (Exception ex) diff --git a/src/presentation/DigitalData.MessagingService.API/Controllers/EmailController.cs b/src/presentation/DigitalData.MessagingService.API/Controllers/EmailController.cs index da5f926..ec252a5 100644 --- a/src/presentation/DigitalData.MessagingService.API/Controllers/EmailController.cs +++ b/src/presentation/DigitalData.MessagingService.API/Controllers/EmailController.cs @@ -78,9 +78,16 @@ public class EmailController(IMediator mediator) : ControllerBase [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task FetchEmails([FromQuery] FetchEmailsQuery query, CancellationToken cancellationToken = default) + public async Task FetchEmails([FromQuery] FetchEmailsQuery query, [FromQuery] bool firstHtmlBodyOnly = false, CancellationToken cancellationToken = default) { var emails = await mediator.Send(query, cancellationToken); + + if(!emails.Any()) + return NotFound("No emails found matching the specified criteria."); + + if (firstHtmlBodyOnly && emails.FirstOrDefault()?.HtmlBody is string htmlBody) + return Ok(htmlBody); + return Ok(emails); }