Send Emails Using a Dedicated Custom Email Sending Service

Create an email sending microservice (really just a template) to speed up sending emails in your new projects.

ebeeraheem

View Profile
132 views
Jun 14, 2025
Updated Jun 22, 2025

Start by creating a new email microservice that exposes a single endpoint api/Email/Send and accepts the following payload:

{
   "to": "sample.user@example.com",
   "subject": "Save Time on Future Projects",
   "body": "Prepare to save some time.",
   "isBodyHtml": false
}

Now, whenever you need to add email sending to a project you're working on, simply deploy this at a subdomain like emailservice.example.com

Create a new EmailService folder in your Infrastructure layer and add EmailServiceOptions.cs file that has a single BaseUrl property. In hindsight, I could've just used the primitive string type without the overhead of the Options pattern.

Then create the EmailRequest.cs file (you can use a record for immutability):

public class EmailRequest
{
   public required string To { get; set; }
   public required string Subject { get; set; }
   public required string Body { get; set; }
   public bool IsHtmlBody { get; set; }
}

Create the IEmailSender interface

public interface IEmailSender
{
   Task SendEmailAsync(EmailRequest emailRequest);
}

Implement it

public class EmailSender : IEmailSender
{
   private readonly HttpClient _httpClient;
   private readonly ILogger<EmailSender> _logger;
   public EmailSender(IHttpClientFactory httpClientFactory, ILogger<EmailSender> logger)
   {
       _httpClient = httpClientFactory.CreateClient("EmailService");
       _logger = logger;
   }
   public async Task SendEmailAsync(EmailRequest emailRequest)
   {
       _logger.LogInformation("Sending email to {To}", emailRequest.To);
       var request = new HttpRequestMessage
       {
           Method = HttpMethod.Post,
           Content = JsonContent.Create(emailRequest),
       };
       var response = await _httpClient.SendAsync(request);
       if (!response.IsSuccessStatusCode)
       {
           _logger.LogError("Failed to send email to {To}: {StatusCode}", emailRequest.To, response.StatusCode);
           var errorContent = await response.Content.ReadAsStringAsync();
           _logger.LogError("Error content: {ErrorContent}", errorContent);
           throw new InvalidOperationException(
               $"Failed to send email. Status code: {response.StatusCode}, Error: {errorContent}");
       }
       _logger.LogInformation("Email sent successfully to {To}", emailRequest.To);
   }
}

And register the service in your service collection (i.e dependency injection container)

        var emailServiceConfig = configuration
           .GetSection("EmailService")
           .Get<EmailServiceOptions>()
           ?? throw new InvalidOperationException("EmailService configuration is missing.");
       services.AddHttpClient("EmailService", client =>
       {
           client.BaseAddress = new Uri(emailServiceConfig.BaseUrl);
           client.DefaultRequestHeaders.Add("Accept", "application/json");
       });
       services.Configure<EmailServiceOptions>(configuration.GetSection("EmailService"));
       services.AddHttpContextAccessor();
       services.AddScoped<IEmailSender, EmailSender>();

Add the email service configurations to your appsettings.json file (or whatever method you see fit for your use case)

  "EmailService": {
   "BaseUrl": "https://emailservice.example.com/api/Email/send"
 }

And that is it. You can now inject the email service interface in your services and start sending emails in minutes.