Code Examples

Real-world code examples ready to use. Copy, paste, and customize according to your needs.

6
Code Examples
3
Difficulty Levels
15+
Features
100%
Tested

Basic

A simple SMTP server in its most basic form

Beginner
BasicExample.cs
using Zetian;

// Basic SMTP server - accepts all messages
using var server = new SmtpServerBuilder()
    .Port(25)
    .ServerName("My SMTP Server")
    .MaxMessageSizeMB(10)
    .Build();

server.MessageReceived += async (sender, e) => {
    Console.WriteLine($"New message from {e.Message.From}");
    Console.WriteLine($"Subject: {e.Message.Subject}");
    
    // Save message to file
    var fileName = $"message_{e.Message.Id}.eml";
    await e.Message.SaveToFileAsync(fileName);
};

await server.StartAsync();
Console.WriteLine("SMTP Server is running on port 25");
Async/AwaitEvent-DrivenProduction Ready

Authenticated

Secure server with username and password

Intermediate
AuthenticatedExample.cs
using Zetian;
using Zetian.Authentication;

// Authenticated SMTP server
using var server = new SmtpServerBuilder()
    .Port(587)
    .RequireAuthentication()
    .AllowPlainTextAuthentication() // For testing without TLS
    .AuthenticationHandler(async (username, password) =>
    {
        // Example: Check hardcoded credentials
        if (username == "testuser" && password == "testpass")
        {
            return AuthenticationResult.Succeed(username);
        }
        
        // In production, validate against a database:
        // if (await CheckDatabase(username, password))
        //     return AuthenticationResult.Succeed(username);
        
        return AuthenticationResult.Fail();
    })
    .AddAuthenticationMechanism("PLAIN")
    .AddAuthenticationMechanism("LOGIN")
    .Build();

server.MessageReceived += (sender, e) => {
    if (e.Session.IsAuthenticated)
    {
        Console.WriteLine($"User {e.Session.AuthenticatedIdentity} sent message");
        Console.WriteLine($"Subject: {e.Message.Subject}");
    }
};

await server.StartAsync();
Console.WriteLine("SMTP Server with authentication on port 587");
Async/AwaitEvent-DrivenProduction Ready

Secure

Encrypted connections with STARTTLS

Intermediate
SecureExample.cs
using Zetian;
using Zetian.Authentication;

// Secure SMTP server with TLS/SSL support
using var server = new SmtpServerBuilder()
    .Port(587)
    .Certificate("certificate.pfx", "password")
    .RequireSecureConnection()
    .RequireAuthentication()
    .SimpleAuthentication("admin", "admin123")
    .Build();

server.SessionCreated += (sender, e) => {
    Console.WriteLine($"New {(e.Session.IsSecure ? "SECURE" : "INSECURE")} connection");
    Console.WriteLine($"  From: {e.Session.RemoteEndPoint}");
};

server.MessageReceived += (sender, e) => {
    if (e.Session.IsSecure)
    {
        Console.WriteLine("Message received over secure connection");
    }
};

await server.StartAsync();
Console.WriteLine("Secure SMTP Server running with STARTTLS support on port 587");
Async/AwaitEvent-DrivenProduction Ready

Rate Limited

Speed limiting for spam protection

Intermediate
RateLimitedExample.cs
using Zetian.Extensions;
using Zetian.Extensions.RateLimiting;

// SMTP server protected with rate limiting
using var server = new SmtpServerBuilder()
    .Port(25)
    .MaxConnections(100)
    .MaxConnectionsPerIP(5)
    .Build();

// Add rate limiting - 100 messages per hour per IP
server.AddRateLimiting(RateLimitConfiguration.PerHour(100));

// Alternative configurations:
// server.AddRateLimiting(RateLimitConfiguration.PerMinute(10));
// server.AddRateLimiting(RateLimitConfiguration.PerDay(1000));

server.MessageReceived += (sender, e) => {
    Console.WriteLine($"Message from {e.Session.RemoteEndPoint}");
    // Rate limiting is handled automatically
    // Messages exceeding limit get SMTP error 421
};

server.ErrorOccurred += (sender, e) => {
    if (e.Exception.Message.Contains("rate limit"))
        Console.WriteLine($"Rate limit exceeded: {e.Session?.RemoteEndPoint}");
};

await server.StartAsync();
Console.WriteLine("Rate-limited server on port 25");
Async/AwaitEvent-DrivenProduction Ready

Custom Processing

Domain and content-based filtering

Advanced
CustomProcessingExample.cs
using Zetian;

// Protocol-level filtering
using var server = new SmtpServerBuilder()
    .Port(25)
    // Only accept messages from these domains
    .WithSenderDomainWhitelist("trusted.com", "partner.org")
    // Block these domains
    .WithSenderDomainBlacklist("spam.com", "junk.org")
    // Only accept messages to these domains
    .WithRecipientDomainWhitelist("mydomain.com", "mycompany.com")
    .Build();

// Event-based filtering
server.MessageReceived += (sender, e) => {
    var message = e.Message;
    
    // Check for spam words
    var spamWords = new[] { "viagra", "lottery", "winner" };
    if (spamWords.Any(word => message.Subject?.Contains(word, StringComparison.OrdinalIgnoreCase) ?? false))
    {
        e.Cancel = true;
        e.Response = new SmtpResponse(550, "Message rejected: Spam detected");
        return;
    }
    
    // Check message size
    if (message.Size > 10_000_000) // 10MB
    {
        e.Cancel = true;
        e.Response = new SmtpResponse(552, "Message too large");
        return;
    }
    
    Console.WriteLine("Message passed all filters");
};

await server.StartAsync();
Async/AwaitEvent-DrivenProduction Ready

Message Storage

Saving messages to file system or database

Advanced
MessageStorageExample.cs
using Zetian;
using Zetian.Storage;
using System.Text.Json;

// SMTP server with built-in file storage
using var server = new SmtpServerBuilder()
    .Port(25)
    // Save messages to file system automatically
    .WithFileMessageStore(@"C:\smtp_messages", createDateFolders: true)
    .Build();

// Using custom message store
// var customStore = new JsonMessageStore(@"C:\email_storage");
// var server = new SmtpServerBuilder()
//     .Port(25)
//     .MessageStore(customStore)
//     .Build();

// Log when messages are received and stored
server.MessageReceived += (sender, e) => {
    Console.WriteLine($"Message {e.Message.Id} saved");
    Console.WriteLine($"From: {e.Message.From?.Address}");
    Console.WriteLine($"Subject: {e.Message.Subject}");
};

// Use custom store: .MessageStore(new JsonMessageStore(@"C:\email_storage"))
await server.StartAsync();

// Custom JSON-based message store
public class JsonMessageStore : IMessageStore
{
    private readonly string _directory;
    
    public JsonMessageStore(string directory)
    {
        _directory = directory;
        Directory.CreateDirectory(directory);
    }
    
    public async Task<bool> SaveAsync(
        ISmtpSession session, 
        ISmtpMessage message, 
        CancellationToken ct)
    {
        var dateFolder = Path.Combine(_directory, DateTime.Now.ToString("yyyy-MM-dd"));
        Directory.CreateDirectory(dateFolder);
        
        // Save raw message
        var emlFile = Path.Combine(dateFolder, $"{message.Id}.eml");
        await message.SaveToFileAsync(emlFile);
        
        // Save metadata as JSON
        var metadata = new {
          Id = message.Id,
          From = message.From?.Address,
          Recipients = message.Recipients.Select(r => r.Address).ToArray(),
          Subject = message.Subject,
          TextBody = message.TextBody,
          HtmlBody = message.HtmlBody,
          Size = message.Size,
          ReceivedDate = DateTime.UtcNow,
          SessionId = session.Id,
          RemoteEndPoint = (session.RemoteEndPoint as IPEndPoint)?.Address?.ToString(),
          IsAuthenticated = session.IsAuthenticated,
          AuthenticatedUser = session.AuthenticatedIdentity
        };
        
        var jsonFile = Path.Combine(dateFolder, $"{message.Id}.json");
        await File.WriteAllTextAsync(jsonFile, 
            JsonSerializer.Serialize(metadata, 
                new JsonSerializerOptions { WriteIndented = true }), ct);
        
        return true;
    }
}
Async/AwaitEvent-DrivenProduction Ready

Looking for More Examples?

Find more examples and test scenarios in our GitHub repository.

View All Examples on GitHub