Noundry.Sanquhar.SendGrid 1.0.0
by Noundry
Noundry.Sanquhar
A flexible and powerful mailing library for .NET 9.0 and .NET 10.0 applications that separates email template rendering from email sending, allowing developers to easily create and send emails with dynamic content.
Features
- Template Rendering: Render email templates using Razor syntax with model data binding
- Multiple Sending Providers: Support for SMTP, SendGrid, and Mailgun
- Email Validation: Built-in email address validation
- Template Caching: Improve performance with automatic template caching
- Dependency Injection: Full DI support for easy integration into ASP.NET Core applications
- Comprehensive Logging: Built-in logging using Microsoft.Extensions.Logging
- Attachments: Support for email attachments
- HTML & Plain Text: Send multipart emails with both HTML and plain text versions
- Custom Headers: Add custom email headers
- Priority Support: Set email priority levels (Low, Normal, High)
Installation
Install the base package:
dotnet add package Noundry.Sanquhar
For SendGrid support:
dotnet add package Noundry.Sanquhar.SendGrid
For Mailgun support:
dotnet add package Noundry.Sanquhar.Mailgun
Quick Start
1. Configure in appsettings.json
{
"Sanquhar": {
"TemplatePath": "EmailTemplates",
"EnableTemplateCache": true,
"TemplateCacheExpirationMinutes": 60,
"Smtp": {
"Host": "smtp.example.com",
"Port": 587,
"Username": "user@example.com",
"Password": "your-password",
"EnableSsl": true
},
"Mail": {
"DefaultFrom": "noreply@example.com",
"DefaultFromName": "My Application",
"DefaultReplyTo": "support@example.com",
"EnableEmailValidation": true
}
}
}
2. Register Services in Program.cs
Using SMTP:
using Noundry.Sanquhar.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Add Sanquhar with SMTP
builder.Services.AddSanquhar(builder.Configuration);
var app = builder.Build();
app.Run();
Using SendGrid:
using Noundry.Sanquhar.Extensions;
using Noundry.Sanquhar.SendGrid.Extensions;
builder.Services.AddSanquhar(builder.Configuration, options =>
options.UseSendGrid(builder.Configuration));
Using Mailgun:
using Noundry.Sanquhar.Extensions;
using Noundry.Sanquhar.Mailgun.Extensions;
builder.Services.AddSanquhar(builder.Configuration, options =>
options.UseMailgun(builder.Configuration));
3. Create Email Templates
Create a directory named EmailTemplates in your project root.
Welcome.cshtml (HTML body):
@model WelcomeEmailModel
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Welcome, @Model.Username!</h1>
<p>Thank you for joining on @Model.RegistrationDate.ToString("D").</p>
</body>
</html>
Welcome_Subject.cshtml (Subject line):
@model WelcomeEmailModel
Welcome to Our Service, @Model.Username!
Welcome_Text.cshtml (Optional plain text version):
@model WelcomeEmailModel
Hello, @Model.Username!
Thank you for joining on @Model.RegistrationDate.ToString("D").
4. Send Emails
From a Controller or Service:
using Noundry.Sanquhar.Services;
public class UserService
{
private readonly IMailService _mailService;
public UserService(IMailService mailService)
{
_mailService = mailService;
}
public async Task SendWelcomeEmail(string email, string username)
{
var model = new WelcomeEmailModel
{
Username = username,
RegistrationDate = DateTime.Now
};
// Create email from template
var message = await _mailService.CreateFromTemplateAsync("Welcome", model);
message.To.Add(email);
// Send email
await _mailService.SendAsync(message);
}
// OR use shorthand method
public async Task SendWelcomeEmailShorthand(string email, string username)
{
var model = new WelcomeEmailModel
{
Username = username,
RegistrationDate = DateTime.Now
};
await _mailService.SendFromTemplateAsync("Welcome", model, email);
}
}
public class WelcomeEmailModel
{
public string Username { get; set; }
public DateTime RegistrationDate { get; set; }
}
Sending without Templates:
using Noundry.Sanquhar.Models;
using Noundry.Sanquhar.Services;
public class NotificationService
{
private readonly IMailService _mailService;
public NotificationService(IMailService mailService)
{
_mailService = mailService;
}
public async Task SendSimpleEmail(string to, string subject, string body)
{
var message = new MailMessage
{
Subject = subject,
HtmlBody = $"<html><body>{body}</body></html>",
Body = body
};
message.To.Add(to);
await _mailService.SendAsync(message);
}
}
Configuration Options
Sanquhar Options
| Property | Type | Default | Description |
|---|---|---|---|
| TemplatePath | string | "EmailTemplates" | Directory containing email templates |
| EnableTemplateCache | bool | true | Enable template caching for performance |
| TemplateCacheExpirationMinutes | int | 60 | Template cache expiration time in minutes |
SMTP Settings
| Property | Type | Default | Description |
|---|---|---|---|
| Host | string | - | SMTP server hostname |
| Port | int | 587 | SMTP server port |
| Username | string | - | SMTP authentication username |
| Password | string | - | SMTP authentication password |
| EnableSsl | bool | true | Enable SSL/TLS |
| Timeout | int | 10000 | Connection timeout in milliseconds |
SendGrid Settings
Add to appsettings.json:
{
"Sanquhar": {
"SendGrid": {
"ApiKey": "your-sendgrid-api-key",
"EnableClickTracking": true,
"EnableOpenTracking": true,
"SandboxMode": false
}
}
}
Mailgun Settings
Add to appsettings.json:
{
"Sanquhar": {
"Mailgun": {
"ApiKey": "your-mailgun-api-key",
"Domain": "your-domain.mailgun.org",
"ApiBaseUrl": "https://api.mailgun.net/v3",
"EnableTracking": true,
"EnableClickTracking": true,
"EnableOpenTracking": true
}
}
}
Mail Settings
| Property | Type | Default | Description |
|---|---|---|---|
| DefaultFrom | string | - | Default sender email address |
| DefaultFromName | string | null | Default sender display name |
| DefaultReplyTo | string | null | Default reply-to email address |
| EnableEmailValidation | bool | true | Enable email address validation |
Advanced Usage
Adding Attachments
var message = await _mailService.CreateFromTemplateAsync("Invoice", model);
message.To.Add(customer.Email);
// Add attachment
message.Attachments.Add(new MailAttachment
{
FileName = "invoice.pdf",
Content = pdfBytes,
ContentType = "application/pdf"
});
await _mailService.SendAsync(message);
Setting Priority
var message = new MailMessage
{
Subject = "Urgent: Action Required",
HtmlBody = urgentMessageBody,
Priority = MailPriority.High
};
message.To.Add(recipient);
await _mailService.SendAsync(message);
Adding CC and BCC Recipients
var message = await _mailService.CreateFromTemplateAsync("Notification", model);
message.To.Add("primary@example.com");
message.Cc.Add("manager@example.com");
message.Bcc.Add("admin@example.com");
await _mailService.SendAsync(message);
Custom Headers
var message = new MailMessage
{
Subject = "Custom Email",
HtmlBody = body
};
message.Headers.Add("X-Custom-Header", "CustomValue");
message.Headers.Add("X-Campaign-ID", campaignId);
message.To.Add(recipient);
await _mailService.SendAsync(message);
Template Naming Conventions
Sanquhar follows these naming conventions for templates:
- [TemplateName].cshtml: Main HTML body template
- [TemplateName]_Subject.cshtml: Subject line template
- [TemplateName]_Text.cshtml: Plain text version (optional)
For example, for a "Welcome" email:
Welcome.cshtml- HTML bodyWelcome_Subject.cshtml- Subject lineWelcome_Text.cshtml- Plain text version
Dependency Injection
Sanquhar registers the following services:
IMailService- High-level email serviceIMailSender- Email sending implementation (SMTP, SendGrid, or Mailgun)ITemplateRenderer- Template rendering engineIEmailValidator- Email address validation
All services are registered as Scoped by default.
Logging
Sanquhar uses Microsoft.Extensions.Logging throughout. To see detailed logs, configure logging in appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Noundry.Sanquhar": "Debug"
}
}
}
Demo Application
The Demo project includes a complete working example with:
- RESTful API endpoints for sending emails
- Sample email templates
- Configuration examples for all providers
- Scalar UI for interactive API testing (modern .NET 9)
To run the demo:
cd Demo
dotnet run
Navigate to https://localhost:5001/scalar/v1 to explore the API with Scalar's beautiful UI.
Best Practices
- Use Templates: Leverage Razor templates for maintainable, reusable email content
- Enable Caching: Keep template caching enabled in production for better performance
- Email Validation: Keep email validation enabled to catch errors early
- Environment-Specific Configuration: Use different SMTP/API settings for development and production
- Logging: Configure appropriate log levels to monitor email delivery
- Error Handling: Always wrap email sending in try-catch blocks and handle failures gracefully
- Testing: Use sandbox mode for SendGrid or test SMTP servers during development
Troubleshooting
Templates Not Found
Ensure your template path is correct:
- Check
TemplatePathinappsettings.json - Verify template files exist in the specified directory
- Ensure template files have
.cshtmlextension
SMTP Connection Errors
- Verify SMTP host and port are correct
- Check username and password
- Ensure
EnableSslmatches your SMTP server requirements - Check firewall settings
SendGrid/Mailgun API Errors
- Verify API key is valid
- Check API key has appropriate permissions
- For Mailgun, ensure domain is correctly configured
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License.
Support
For issues, questions, or feature requests, please open an issue on GitHub.
.NET 8.0
- Noundry.Sanquhar (>= 1.0.0)
- SendGrid (>= 9.29.3)
.NET 9.0
- Noundry.Sanquhar (>= 1.0.0)
- SendGrid (>= 9.29.3)
.NET 10.0
- Noundry.Sanquhar (>= 1.0.0)
- SendGrid (>= 9.29.3)
No packages depend on Noundry.Sanquhar.SendGrid.
Initial release v1.0.0 - SendGrid integration with tracking features and sandbox mode.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 Current | 0 | 12/30/2025 |
Info
- Last updated 26 days ago
- License
- Download package
Statistics
- Total Downloads
- 0
- Current Version Downloads
- 0
Authors
Noundry