FluentEmail is a lightweight, flexible library that makes sending email from .NET applications easy, maintainable, and testable. This guide explains everything you need to build production-ready email functionality using FluentEmail — from installation and SMTP configuration to templates, providers, testing, security, and best practices.
Contents
- Why use FluentEmail?
- Core concepts
- Installation
- Basic SMTP usage
- Razor templates and templating best practices
- Using third-party providers (SendGrid, Mailgun)
- Attachments, inline images, and advanced content
- Integration with ASP.NET Core
- Testing and local development
- Security and deliverability best practices
- Troubleshooting common issues
- Complete working examples
- Summary & further reading
1. Why use FluentEmail?
- Readable API:
Email.From(...).To(...).Subject(...).Body(...)
3. Installation
Install-Package FluentEmail.Core
Install-Package FluentEmail.Smtp
Install-Package FluentEmail.Razor
Install-Package FluentEmail.SendGrid
Install-Package FluentEmail.Mailgun
4. Basic SMTP usage
// using FluentEmail.Smtp;
// using System.Net;
// using System.Net.Mail;
var sender = new SmtpSender(() => new SmtpClient("smtp.gmail.com")
{
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
Port = 587,
Credentials = new NetworkCredential(
"your_email@gmail.com",
"your_password_or_app_password"
)
});
Email.DefaultSender = sender;
var response = await Email
.From("no-reply@myapp.com")
.To("user@example.com", "User Name")
.Subject("Welcome to MyApp")
.Body("Hello! Thanks for signing up.")
.SendAsync();
if (response.Successful)
Console.WriteLine("Sent");
else
Console.WriteLine(string.Join("; ", response.ErrorMessages));
await Email
.From("no-reply@myapp.com")
.To("user@example.com")
.Subject("Your Order")
.Body("<h1>Thanks</h1><p>Your order is ready.</p>", isHtml: true)
.PlaintextAlternateBody("Thanks — your order is ready.")
.SendAsync();
5. Razor templates
Email.DefaultRenderer = new RazorRenderer();
<h1>Welcome @@Model.Name!</h1>
<p>Your account has been created.</p>
<a href="@@Model.VerifyUrl">Verify Email</a>
await Email
.From("no-reply@myapp.com")
.To("newuser@example.com")
.Subject("Welcome!")
.UsingTemplateFromFile(
"Templates/Welcome.cshtml",
new {
Name = "Shahnawaz",
VerifyUrl = "https://example.com/verify/abc"
}
)
.SendAsync();
8. ASP.NET Core Integration
// Program.cs
builder.Services
.AddFluentEmail("no-reply@myapp.com")
.AddRazorRenderer()
.AddSmtpSender(
"smtp.gmail.com",
587,
"your_email@gmail.com",
"your_password_or_app_password"
);
public class NotificationService
{
private readonly IFluentEmail _fluentEmail;
public NotificationService(IFluentEmail fluentEmail)
{
_fluentEmail = fluentEmail;
}
public Task<SendResponse> SendWelcome(
string toEmail,
string name,
string url
) =>
_fluentEmail
.To(toEmail)
.Subject("Welcome")
.UsingTemplateFromFile(
"Templates/Welcome.cshtml",
new { Name = name, VerifyUrl = url }
)
.SendAsync();
}
9. Testing
public class FakeSender : ISender
{
public List<EmailMessage> Sent =
new List<EmailMessage>();
public Task<SendResponse> SendAsync(
EmailMessage message,
CancellationToken token = default
)
{
Sent.Add(message);
return Task.FromResult(
new SendResponse { Successful = true }
);
}
}
12. Complete ASP.NET Core Example
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddFluentEmail("no-reply@myapp.com")
.AddRazorRenderer()
.AddSmtpSender(
"smtp.gmail.com",
587,
builder.Configuration["Smtp:User"],
builder.Configuration["Smtp:Pass"]
);
builder.Services.AddTransient<NotificationService>();
var app = builder.Build();
app.MapGet("/send", async (NotificationService svc) =>
{
await svc.SendWelcome(
"test@example.com",
"Test User",
"https://example.com/verify/123"
);
return Results.Ok("Sent");
});
app.Run();