Linger.Email
1.1.0
dotnet add package Linger.Email --version 1.1.0
NuGet\Install-Package Linger.Email -Version 1.1.0
<PackageReference Include="Linger.Email" Version="1.1.0" />
<PackageVersion Include="Linger.Email" Version="1.1.0" />
<PackageReference Include="Linger.Email" />
paket add Linger.Email --version 1.1.0
#r "nuget: Linger.Email, 1.1.0"
#:package Linger.Email@1.1.0
#addin nuget:?package=Linger.Email&version=1.1.0
#tool nuget:?package=Linger.Email&version=1.1.0
Linger.Email
Overview
Linger.Email is a comprehensive C# email helper library that provides simplified email operations with modern .NET development in mind. Built on top of the robust MailKit library, it offers secure SMTP support, HTML and plain text emails, attachment handling, and asynchronous sending capabilities across multiple .NET frameworks.
Installation
dotnet add package Linger.Email
Features
- Multi-format Email Support: Send both HTML and plain text emails
- Attachment Handling: Support for file attachments with multiple formats
- Secure SMTP: SSL/TLS encryption support for secure email transmission
- Asynchronous Operations: Modern async/await pattern for non-blocking email operations
- Flexible Configuration: Easy-to-use configuration system
- Multiple Recipients: Support for To, CC, and BCC recipients
- Priority Levels: Configure email priority (High, Normal, Low)
- Cross-platform: Supports multiple .NET frameworks (net9.0, net8.0, netstandard2.0)
Quick Start
Basic Configuration
using Linger.Email;
// Configure email settings
var emailConfig = new EmailConfig
{
Host = "smtp.gmail.com",
Port = 587,
UseSsl = true,
UseStartTls = true,
UserName = "your-email@gmail.com",
Password = "your-app-password",
From = new EmailAddress("your-email@gmail.com", "Your Name")
};
// Create email client
using var email = new Email(emailConfig);
Send Simple Text Email
// Create email message
var message = new EmailMessage
{
To = new List<EmailAddress> { new("recipient@example.com", "Recipient Name") },
Subject = "Hello from Linger.Email",
Body = "This is a simple text email.",
IsHtmlBody = false
};
// Send email
await email.SendAsync(message);
// Send email with cancellation support
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await email.SendAsync(message, cancellationToken: cts.Token);
Send HTML Email
var htmlMessage = new EmailMessage
{
To = new List<EmailAddress> { new("recipient@example.com") },
Subject = "HTML Email Example",
Body = @"
<h1>Welcome!</h1>
<p>This is an <strong>HTML email</strong> sent using Linger.Email.</p>
<ul>
<li>Feature 1</li>
<li>Feature 2</li>
<li>Feature 3</li>
</ul>
",
IsHtmlBody = true
};
await email.SendAsync(htmlMessage);
Send Email with Attachments
var messageWithAttachments = new EmailMessage
{
To = new List<EmailAddress> { new("recipient@example.com") },
Subject = "Email with Attachments",
Body = "Please find the attached files.",
IsHtmlBody = false,
AttachmentsPath = new List<string>
{
@"C:\Documents\report.pdf",
@"C:\Images\chart.png"
}
};
await email.SendAsync(messageWithAttachments);
Send Email with Stream Attachments
// Using AttachmentInfo for stream-based attachments
var attachmentInfos = new List<AttachmentInfo>
{
new()
{
Stream = new MemoryStream(pdfBytes),
FileName = "generated-report.pdf",
MediaType = "application/pdf"
},
new()
{
Stream = imageStream,
FileName = "image.jpg",
MediaType = "image/jpeg"
}
};
var message = new EmailMessage
{
To = new List<EmailAddress> { new("recipient@example.com") },
Subject = "Email with Stream Attachments",
Body = "Generated attachments from streams.",
Attachments = attachmentInfos
};
await email.SendAsync(message);
Advanced Features
Multiple Recipients with CC and BCC
var message = new EmailMessage
{
To = new List<EmailAddress>
{
new("primary@example.com", "Primary Recipient"),
new("secondary@example.com", "Secondary Recipient")
},
Cc = new List<EmailAddress>
{
new("manager@example.com", "Manager")
},
Bcc = new List<EmailAddress>
{
new("archive@example.com", "Archive")
},
Subject = "Team Update",
Body = "Important team announcement...",
Priority = MessagePriority.High
};
await email.SendAsync(message);
Email with Callback
await email.SendAsync(message, response =>
{
Console.WriteLine($"Email sent successfully: {response}");
// Log the response or perform additional actions
});
// Email with callback and cancellation support
using var cts = new CancellationTokenSource();
await email.SendAsync(
message,
response => Console.WriteLine($"Email sent: {response}"),
cts.Token
);
Different SMTP Configurations
Gmail Configuration
var gmailConfig = new EmailConfig
{
Host = "smtp.gmail.com",
Port = 587,
UseSsl = true,
UseStartTls = true,
UserName = "your-email@gmail.com",
Password = "your-app-password", // Use App Password, not regular password
From = new EmailAddress("your-email@gmail.com", "Your Name")
};
Outlook Configuration
var outlookConfig = new EmailConfig
{
Host = "smtp-mail.outlook.com",
Port = 587,
UseSsl = false,
UseStartTls = true,
UserName = "your-email@outlook.com",
Password = "your-password",
From = new EmailAddress("your-email@outlook.com", "Your Name")
};
Custom SMTP Server
var customConfig = new EmailConfig
{
Host = "mail.your-domain.com",
Port = 25,
UseSsl = false,
UseStartTls = false,
UserName = "username",
Password = "password",
From = new EmailAddress("noreply@your-domain.com", "Your App Name")
};
Global BCC Configuration
var config = new EmailConfig
{
Host = "smtp.example.com",
Port = 587,
UseSsl = true,
UserName = "sender@example.com",
Password = "password",
From = new EmailAddress("sender@example.com", "Sender"),
Bcc = new List<EmailAddress>
{
new("audit@example.com", "Audit Trail"),
new("backup@example.com", "Backup Archive")
}
};
Error Handling
try
{
await email.SendAsync(message);
Console.WriteLine("Email sent successfully!");
}
catch (AuthenticationException ex)
{
Console.WriteLine($"Authentication failed: {ex.Message}");
// Handle authentication errors
}
catch (SmtpException ex)
{
Console.WriteLine($"SMTP error: {ex.Message}");
// Handle SMTP-specific errors
}
catch (Exception ex)
{
Console.WriteLine($"General error: {ex.Message}");
// Handle other errors
}
Best Practices
- Use App Passwords: For Gmail and other providers, use app-specific passwords instead of regular passwords
- Dispose Properly: Always use
usingstatements or proper disposal patterns - Validate Email Addresses: Validate email addresses before sending
- Handle Exceptions: Implement proper exception handling for network and authentication issues
- Stream Management: Properly dispose of streams when using stream-based attachments
- Configuration Security: Store email credentials securely (e.g., Azure Key Vault, user secrets)
Cancellation Support
All async email operations support CancellationToken for graceful cancellation:
public class EmailService
{
private readonly IEmail _email;
public EmailService(IEmail email)
{
_email = email;
}
// Send email with timeout
public async Task<bool> SendEmailWithTimeoutAsync(EmailMessage message, int timeoutSeconds = 30)
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds));
try
{
await _email.SendAsync(message, cancellationToken: cts.Token);
return true;
}
catch (OperationCanceledException)
{
Console.WriteLine("Email sending was cancelled due to timeout");
return false;
}
}
// Send email with external cancellation
public async Task SendBulkEmailsAsync(
List<EmailMessage> messages,
CancellationToken cancellationToken)
{
foreach (var message in messages)
{
// Check if cancellation was requested
cancellationToken.ThrowIfCancellationRequested();
await _email.SendAsync(message, cancellationToken: cancellationToken);
// Optional: Add delay between emails
await Task.Delay(1000, cancellationToken);
}
}
}
Using with ASP.NET Core Request Cancellation
[ApiController]
[Route("api/[controller]")]
public class EmailController : ControllerBase
{
private readonly IEmailService _emailService;
public EmailController(IEmailService emailService)
{
_emailService = emailService;
}
[HttpPost("send")]
public async Task<IActionResult> SendEmail(
[FromBody] EmailRequest request,
CancellationToken cancellationToken)
{
try
{
// Pass the request's cancellation token
// Will automatically cancel if client disconnects
await _emailService.SendTextEmailAsync(
request.To,
request.Subject,
request.Body,
cancellationToken
);
return Ok("Email sent successfully");
}
catch (OperationCanceledException)
{
return StatusCode(499, "Request cancelled by client");
}
}
}
Performance Tips
- Connection Reuse: Reuse SMTP connections for better performance when sending multiple emails
- Batch Processing: Send emails in batches to reduce connection overhead
- Async Processing: Use background services for high-volume email processing
- Configuration Optimization: Set appropriate timeout and retry policies
- Resource Management: Properly dispose of resources, especially when using streams
- Error Handling: Implement retry logic for transient failures
- Cancellation Tokens: Use cancellation tokens to prevent resource waste on cancelled operations
Common Use Cases
Password Reset Email
var resetMessage = new EmailMessage
{
To = new List<EmailAddress> { new(userEmail, userName) },
Subject = "Password Reset Request",
Body = $@"
<h2>Password Reset</h2>
<p>Hello {userName},</p>
<p>Click the link below to reset your password:</p>
<a href='{resetLink}'>Reset Password</a>
<p>This link expires in 24 hours.</p>
",
IsHtmlBody = true
};
await email.SendAsync(resetMessage);
Order Confirmation Email
var orderMessage = new EmailMessage
{
To = new List<EmailAddress> { new(customerEmail, customerName) },
Subject = $"Order Confirmation - #{orderNumber}",
Body = GenerateOrderConfirmationHtml(order),
IsHtmlBody = true,
AttachmentsPath = new List<string> { invoicePdfPath }
};
await email.SendAsync(orderMessage);
System Notification Email
var notificationMessage = new EmailMessage
{
To = adminEmails,
Subject = "System Alert: High CPU Usage",
Body = "System performance alert...",
Priority = MessagePriority.High
};
await email.SendAsync(notificationMessage);
Core Classes
EmailConfig
Configuration class that holds SMTP server settings, authentication credentials, and default sender information.
EmailMessage
Represents an email message with recipients, subject, body, attachments, and other properties.
EmailAddress
Represents an email address with optional display name.
AttachmentInfo
Represents an email attachment with stream, filename, and media type information.
Main email client class that handles SMTP connections and message sending.
Dependencies
- MailKit: A cross-platform .NET library for IMAP, POP3, and SMTP
- MimeKit: A .NET MIME creation and parser library
Supported .NET Versions
- .NET 10.0
- .NET 9.0
- .NET 8.0
- .NET Standard 2.0
Integration
📖 For ASP.NET Core integration and dependency injection support, see: Linger.Email.AspNetCore README
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Linger.Utils (>= 1.1.0)
- MailKit (>= 4.14.1)
- MimeKit (>= 4.14.0)
-
net10.0
- Linger.Utils (>= 1.1.0)
- MailKit (>= 4.14.1)
- MimeKit (>= 4.14.0)
-
net8.0
- Linger.Utils (>= 1.1.0)
- MailKit (>= 4.14.1)
- MimeKit (>= 4.14.0)
-
net9.0
- Linger.Utils (>= 1.1.0)
- MailKit (>= 4.14.1)
- MimeKit (>= 4.14.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Linger.Email:
| Package | Downloads |
|---|---|
|
Linger.Email.AspNetCore
ASP.NET Core integration for the Linger.Email library. Provides dependency injection extensions and configuration integration for email services. Simplifies email sending in modern ASP.NET Core applications. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.0 | 112 | 2/4/2026 |
| 1.0.3-preview | 115 | 1/9/2026 |
| 1.0.2-preview | 118 | 1/8/2026 |
| 1.0.0 | 320 | 11/12/2025 |
| 1.0.0-preview2 | 206 | 11/6/2025 |
| 1.0.0-preview1 | 210 | 11/5/2025 |
| 0.9.9 | 215 | 10/16/2025 |
| 0.9.8 | 208 | 10/14/2025 |
| 0.9.7-preview | 193 | 10/13/2025 |
| 0.9.6-preview | 177 | 10/12/2025 |
| 0.9.5 | 187 | 9/28/2025 |
| 0.9.4-preview | 200 | 9/25/2025 |
| 0.9.3-preview | 217 | 9/22/2025 |
| 0.9.1-preview | 320 | 9/16/2025 |
| 0.9.0-preview | 150 | 9/12/2025 |
| 0.8.5-preview | 221 | 8/31/2025 |
| 0.8.4-preview | 347 | 8/25/2025 |
| 0.8.3-preview | 198 | 8/20/2025 |
| 0.8.2-preview | 240 | 8/4/2025 |
| 0.8.1-preview | 176 | 7/30/2025 |