Skip to content

neevan01/FluentMail

Repository files navigation

FluentMail

A lightweight, cross-platform email sending library for .NET Standard 2.0+, .NET Core, and .NET 5+.

Features

  • ✅ .NET Standard 2.0 compatible (works with .NET Framework 4.6.1+, .NET Core 2.0+, .NET 5+)
  • ✅ Multiple recipients (To, Cc, Bcc)
  • ✅ HTML and plain text emails
  • ✅ Attachments support with size validation
  • ✅ SMTP provider with MailKit
  • ✅ Fluent API
  • ✅ Optional logging support (Microsoft.Extensions.Logging)
  • ✅ Automatic retry with exponential backoff
  • ✅ Email validation (format, required fields)
  • ✅ Async/await throughout
  • ✅ Structured result objects (no exceptions for send failures)

Installation

dotnet add package FluentMail

Quick Start

1. Configure in Startup (ASP.NET Core)

services.AddFluentMail(options =>
{
    options.Host = "smtp.gmail.com";
    options.Port = 587;
    options.Username = "your-email@gmail.com";
    options.Password = "your-password";
    options.UseSsl = true;
});

2. Inject and Use

public class MyService
{
    private readonly IEmailService _emailService;

    public MyService(IEmailService emailService)
    {
        _emailService = emailService;
    }

    public async Task SendWelcomeEmail()
    {
        var message = new EmailMessage()
            .From("noreply@example.com", "My App")
            .To("user@example.com", "John Doe")
            .WithSubject("Welcome!")
            .WithHtmlBody("<h1>Welcome to our service!</h1>");

        var result = await _emailService.SendAsync(message);

        if (result.IsSuccess)
        {
            Console.WriteLine($"Email sent! MessageId: {result.MessageId}");
        }
        else
        {
            Console.WriteLine($"Failed: {result.ErrorMessage}");
        }
    }
}

Usage Examples

Multiple Recipients

var message = new EmailMessage()
    .From("sender@example.com")
    .To("user1@example.com")
    .To("user2@example.com")
    .To(new[] { "user3@example.com", "user4@example.com" })
    .Cc("manager@example.com")
    .Bcc("admin@example.com")
    .WithSubject("Team Update")
    .WithBody("Hello team!");

var result = await emailService.SendAsync(message);

With Attachments

var message = new EmailMessage()
    .From("sender@example.com")
    .To("recipient@example.com")
    .WithSubject("Invoice")
    .WithBody("Please find attached invoice")
    .WithAttachment(new EmailAttachment("invoice.pdf", fileStream, "application/pdf"));

var result = await emailService.SendAsync(message);

Without Dependency Injection

var options = new SmtpOptions
{
    Host = "smtp.gmail.com",
    Port = 587,
    Username = "your-email@gmail.com",
    Password = "your-password",
    UseSsl = true
};

var provider = new SmtpEmailProvider(options);
var emailService = new EmailService(provider);

var message = new EmailMessage()
    .From("sender@example.com")
    .To("recipient@example.com")
    .WithSubject("Test")
    .WithBody("Hello!");

var result = await emailService.SendAsync(message);

Configuration Options

public class SmtpOptions
{
    public string Host { get; set; }              // SMTP server host
    public int Port { get; set; }                 // SMTP server port (default: 587)
    public string Username { get; set; }          // SMTP username
    public string Password { get; set; }          // SMTP password
    public bool UseSsl { get; set; }              // Use SSL/TLS (default: true)
    public string? DefaultFromEmail { get; set; } // Optional default sender
    public string? DefaultFromName { get; set; }  // Optional default sender name
    public long MaxAttachmentSize { get; set; }   // Max attachment size in bytes (default: 20MB)
    public int MaxRetries { get; set; }           // Retry attempts for failures (default: 3)
    public int RetryDelayMs { get; set; }         // Initial retry delay in ms (default: 1000)
}

Advanced Configuration

services.AddFluentMail(options =>
{
    options.Host = "smtp.gmail.com";
    options.Port = 587;
    options.Username = "your-email@gmail.com";
    options.Password = "your-password";
    options.UseSsl = true;

    // Attachment validation
    options.MaxAttachmentSize = 10 * 1024 * 1024; // 10MB limit

    // Retry configuration
    options.MaxRetries = 5;        // Retry up to 5 times
    options.RetryDelayMs = 2000;   // Start with 2 second delay
    // Exponential backoff: 2s, 4s, 8s, 16s, 32s
});

Logging

The library integrates seamlessly with Microsoft.Extensions.Logging:

// In Startup.cs or Program.cs
services.AddLogging(builder =>
{
    builder.AddConsole();
    builder.AddDebug();
});

services.AddFluentMail(options => { ... });

Log output includes:

  • Recipient count
  • Send success/failure
  • Message IDs
  • Validation errors

If logging is not configured, the library works silently without errors.

Validation

The library automatically validates:

  • Email address format (RFC-compliant regex)
  • Required fields (From, To, Subject)
  • Total attachment size
  • All recipient email addresses
var result = await emailService.SendAsync(message);

if (!result.IsSuccess)
{
    // Possible validation errors:
    // - "Valid sender email is required"
    // - "At least one recipient is required"
    // - "Invalid email address: xyz"
    // - "Total attachment size (25MB) exceeds limit (20MB)"
    Console.WriteLine(result.ErrorMessage);
}

Retry Logic

Automatic retry with exponential backoff for transient failures:

MaxRetries = 3, RetryDelayMs = 1000
// Attempt 1: Immediate
// Attempt 2: Wait 1s  (1000ms * 2^0)
// Attempt 3: Wait 2s  (1000ms * 2^1)
// Attempt 4: Wait 4s  (1000ms * 2^2)

Retries are automatic and transparent. Check logs to see retry attempts.

Development

Running Tests

cd tests/EmailSender.Tests
dotnet test

The test suite includes:

  • Email validation tests
  • Fluent API tests
  • Retry logic tests
  • Error handling tests
  • SMTP provider tests

Building the Package

cd src/EmailSender
dotnet pack -c Release

License

MIT

About

A lightweight, cross-platform email sending library with automatic retry, validation, and optional logging support

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages