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
267 views
Jun 14, 2025
Updated Jul 18, 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.",
   "isHtmlBody": 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(
    IHttpClientFactory httpClientFactory,
    ILogger<EmailSender> logger) : IEmailSender
{
    private readonly HttpClient _httpClient = httpClientFactory.CreateClient(nameof(EmailSender));

public async Task SendEmailAsync(EmailRequest emailRequest)
{

    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Post,
        Content = JsonContent.Create(emailRequest),
    };

    var response = await _httpClient.SendAsync(request);

    if (response.IsSuccessStatusCode)
    {
        logger.LogInformation(&quot;Email sent successfully to {To}&quot;, emailRequest.To);
        return;
    }

    var errorContent = await response.Content.ReadAsStringAsync();
    logger.LogError(&quot;Failed to send email to {To}. Status code: {StatusCode}, Error: {Error}&quot;,
        emailRequest.To, response.StatusCode, errorContent);

    throw new InvalidOperationException(
        $&quot;Failed to send email. Status code: {response.StatusCode}, Error: {errorContent}&quot;);
}
}

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

// Configure the EmailSender service
var emailUrl = configuration.GetValue<string>("EmailUrl")
    ?? throw new InvalidOperationException("EmailUrl configuration is missing.");

services.AddHttpClient(nameof(EmailSender), client =>
{
    client.BaseAddress = new Uri(emailUrl);
    client.DefaultRequestHeaders.Add("Accept", "application/json");
});

services.AddScoped<IEmailSender, EmailSender>();
services.AddHttpContextAccessor();

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

"EmailUrl": "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.