Rename EmailsController to EmailController

Updated the class name from EmailsController to EmailController to follow a singular naming convention for controller classes. The namespace and constructor signature remain unchanged. This change improves consistency and readability in the codebase without introducing any functional modifications.
This commit is contained in:
2026-08-07 11:50:48 +02:00
parent c47d78112c
commit 18c5dca9f4

View File

@@ -0,0 +1,132 @@
using DigitalData.MessagingService.Application.EmailSending.Commands;
using DigitalData.MessagingService.Application.EmailReceiving.Queries;
using DigitalData.MessagingService.Application.EmailReceiving.Commands;
using DigitalData.MessagingService.Application.EmailAccount.Queries;
using DigitalData.MessagingService.Abstraction;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace DigitalData.MessagingService.API.Controllers;
/// <summary>
/// Email sending API controller.
/// Enqueues outgoing emails to RabbitMQ for async processing.
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class EmailController(IMediator mediator) : ControllerBase
{
#region Send
/// <summary>
/// Send an email, optionally with file attachments.
/// Omit the <c>attachments</c> field for a plain send.
/// </summary>
/// <param name="command">Email fields as form values</param>
/// <param name="attachments">Optional uploaded files</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>HTTP 202 Accepted with the queued event ID</returns>
[HttpPost]
[Consumes("multipart/form-data")]
[ProducesResponseType(StatusCodes.Status202Accepted)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> SendEmail(
[FromForm] PublishEmailCommand command,
IFormFileCollection? attachments,
CancellationToken cancellationToken)
{
var commandWithAttachments = command.WithAttachments(
await BuildAttachmentsAsync(attachments, cancellationToken));
var eventId = await mediator.Send(commandWithAttachments, cancellationToken);
return Accepted(new { Id = eventId });
}
private static async Task<IEnumerable<EmailAttachmentContext>> BuildAttachmentsAsync(
IFormFileCollection? files,
CancellationToken cancellationToken)
{
if (files is null || files.Count == 0)
return [];
var result = new List<EmailAttachmentContext>(files.Count);
foreach (var file in files)
{
using var ms = new MemoryStream();
await file.CopyToAsync(ms, cancellationToken);
result.Add(new EmailAttachmentContext
{
FileName = file.FileName,
Content = ms.ToArray(),
ContentType = file.ContentType
});
}
return result;
}
#endregion Send
#region Receive
/// <summary>
/// Fetch emails from an IMAP mailbox.
/// </summary>
/// <param name="accountId">Id of the email account (must have ImapServer configured).</param>
/// <param name="folder">Mailbox folder to read (default: INBOX).</param>
/// <param name="unseenOnly">Return only unread messages.</param>
/// <param name="maxCount">Maximum number of messages to return (most-recent first, default: 50).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>HTTP 200 with list of received emails.</returns>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> FetchEmails(
[FromQuery] int accountId,
[FromQuery] string folder = "INBOX",
[FromQuery] bool unseenOnly = false,
[FromQuery] int maxCount = 50,
CancellationToken cancellationToken = default)
{
var query = new FetchEmailsQuery
{
Account = new GetSenderQuery { Id = accountId },
Folder = folder,
UnseenOnly = unseenOnly,
MaxCount = maxCount
};
var emails = await mediator.Send(query, cancellationToken);
return Ok(emails);
}
/// <summary>
/// Mark a single IMAP message as seen (read).
/// </summary>
/// <param name="accountId">Id of the email account.</param>
/// <param name="uid">UID of the message on the IMAP server.</param>
/// <param name="folder">Mailbox folder the message resides in (default: INBOX).</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>HTTP 204 No Content.</returns>
[HttpPatch("{uid}/seen")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> MarkAsSeen(
[FromRoute] long uid,
[FromQuery] int accountId,
[FromQuery] string folder = "INBOX",
CancellationToken cancellationToken = default)
{
var command = new MarkEmailAsSeenCommand
{
Account = new GetSenderQuery { Id = accountId },
Uid = uid,
Folder = folder
};
await mediator.Send(command, cancellationToken);
return NoContent();
}
#endregion Receive
}