Linger.Email 1.1.0

dotnet add package Linger.Email --version 1.1.0
                    
NuGet\Install-Package Linger.Email -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Linger.Email" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Linger.Email" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Linger.Email" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Linger.Email --version 1.1.0
                    
#r "nuget: Linger.Email, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Linger.Email@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Linger.Email&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Linger.Email&version=1.1.0
                    
Install as a Cake Tool

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

  1. Use App Passwords: For Gmail and other providers, use app-specific passwords instead of regular passwords
  2. Dispose Properly: Always use using statements or proper disposal patterns
  3. Validate Email Addresses: Validate email addresses before sending
  4. Handle Exceptions: Implement proper exception handling for network and authentication issues
  5. Stream Management: Properly dispose of streams when using stream-based attachments
  6. 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

  1. Connection Reuse: Reuse SMTP connections for better performance when sending multiple emails
  2. Batch Processing: Send emails in batches to reduce connection overhead
  3. Async Processing: Use background services for high-volume email processing
  4. Configuration Optimization: Set appropriate timeout and retry policies
  5. Resource Management: Properly dispose of resources, especially when using streams
  6. Error Handling: Implement retry logic for transient failures
  7. 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.

Email

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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed