Zetian.Relay
1.0.5
Prefix Reserved
dotnet add package Zetian.Relay --version 1.0.5
NuGet\Install-Package Zetian.Relay -Version 1.0.5
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="Zetian.Relay" Version="1.0.5" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Zetian.Relay" Version="1.0.5" />
<PackageReference Include="Zetian.Relay" />
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 Zetian.Relay --version 1.0.5
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Zetian.Relay, 1.0.5"
#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 Zetian.Relay@1.0.5
#: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=Zetian.Relay&version=1.0.5
#tool nuget:?package=Zetian.Relay&version=1.0.5
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Zetian.Relay - SMTP Relay and Proxy Extension
SMTP relay and proxy extension for Zetian SMTP Server with smart host support, queue management, load balancing, and failover mechanisms.
⚡ Features
- 🎚️ Priority Queuing - Message priority support
- 📊 MX Routing - DNS MX record-based routing
- 🔀 Failover - Automatic failover to backup servers
- 📈 Queue Statistics - Real-time queue monitoring
- 💌 Bounce Messages - Automatic NDR generation
- 🎯 Domain Routing - Custom routing rules per domain
- 🌐 TLS/SSL - Secure connections with STARTTLS support
- 🔐 Authentication - Support for AUTH PLAIN and LOGIN
- ⏱️ Retry Logic - Exponential backoff with configurable limits
- ⚖️ Load Balancing - Distribute load across multiple relay servers
- 🔄 Queue Management - Persistent queue with retry mechanisms
- 📬 Smart Host Support - Route messages through configured relay servers
📦 Installation
# Install Zetian SMTP Server (required)
dotnet add package Zetian
# Install Relay Extension
dotnet add package Zetian.Relay
🚀 Quick Start
Basic Relay Setup
using Zetian.Server;
using Zetian.Relay.Extensions;
// Create SMTP server with relay enabled
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay();
// Start server with relay service
var relayService = await server.StartWithRelayAsync();
With Smart Host
using System.Net;
using Zetian.Server;
using Zetian.Relay.Extensions;
using Zetian.Relay.Configuration;
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
config.DefaultSmartHost = new SmartHostConfiguration
{
Host = "smtp.example.com",
Port = 587,
Credentials = new NetworkCredential("user", "password"),
UseTls = true
};
});
await server.StartAsync();
Multiple Smart Hosts with Failover
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Primary smart host
config.DefaultSmartHost = new SmartHostConfiguration
{
Host = "primary.smtp.com",
Port = 587,
Priority = 10,
Credentials = new NetworkCredential("user", "pass")
};
// Backup smart hosts
config.SmartHosts.Add(new SmartHostConfiguration
{
Host = "backup1.smtp.com",
Port = 587,
Priority = 20,
Credentials = new NetworkCredential("user", "pass")
});
config.SmartHosts.Add(new SmartHostConfiguration
{
Host = "backup2.smtp.com",
Port = 587,
Priority = 30
});
});
🎯 Advanced Configuration
Using Relay Builder
using Zetian.Server;
using Zetian.Relay.Builder;
using Zetian.Relay.Extensions;
var relayConfig = new RelayBuilder()
.WithSmartHost("smtp.office365.com", 587, "user@domain.com", "password")
.MaxConcurrentDeliveries(20)
.MaxRetries(5)
.MessageLifetime(TimeSpan.FromDays(3))
.ConnectionTimeout(TimeSpan.FromMinutes(10))
.EnableTls(true, require: true)
.LocalDomain("mail.mydomain.com")
.AddLocalDomains("mydomain.com", "internal.local")
.AddRelayDomains("partner.com", "customer.com")
.RequireAuthentication(true)
.EnableBounce(true, "postmaster@mydomain.com")
.Build();
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(relayConfig);
Domain-Specific Routing
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Route specific domains through different smart hosts
config.DomainRouting["gmail.com"] = new SmartHostConfiguration
{
Host = "smtp.gmail.com",
Port = 587,
Credentials = new NetworkCredential("user@gmail.com", "app_password")
};
config.DomainRouting["outlook.com"] = new SmartHostConfiguration
{
Host = "smtp-mail.outlook.com",
Port = 587,
Credentials = new NetworkCredential("user@outlook.com", "password")
};
// Default for all other domains
config.DefaultSmartHost = new SmartHostConfiguration
{
Host = "smtp.sendgrid.net",
Port = 587,
Credentials = new NetworkCredential("apikey", "SG.xxxxx")
};
});
MX-Based Routing
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Use DNS MX records for routing
config.UseMxRouting = true;
// Optional: Custom DNS servers
config.DnsServers.Add(IPAddress.Parse("8.8.8.8"));
config.DnsServers.Add(IPAddress.Parse("1.1.1.1"));
// Fallback smart host if MX lookup fails
config.DefaultSmartHost = new SmartHostConfiguration
{
Host = "fallback.smtp.com",
Port = 25
};
});
Relay Networks Configuration
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Allow relay from specific IP addresses without authentication
config.RelayNetworks.Add(IPAddress.Parse("192.168.1.0"));
config.RelayNetworks.Add(IPAddress.Parse("10.0.0.0"));
// Require authentication for all others
config.RequireAuthentication = true;
});
📊 Queue Management
Manual Queue Operations
// Get relay service
var relayService = server.GetRelayService();
// Queue a message manually
var relayMessage = await server.QueueForRelayAsync(
message,
session,
RelayPriority.High);
// Get queue statistics
var stats = await server.GetRelayStatisticsAsync();
Console.WriteLine($"Queued: {stats.QueuedMessages}");
Console.WriteLine($"In Progress: {stats.InProgressMessages}");
Console.WriteLine($"Delivered: {stats.DeliveredMessages}");
Console.WriteLine($"Failed: {stats.FailedMessages}");
// Get all messages in queue
var messages = await relayService.Queue.GetAllAsync();
// Get messages by status
var deferredMessages = await relayService.Queue.GetByStatusAsync(RelayStatus.Deferred);
// Remove a message
await relayService.Queue.RemoveAsync(queueId);
// Clear expired messages
var cleared = await relayService.Queue.ClearExpiredAsync();
Message Priority
server.MessageReceived += async (sender, e) =>
{
// Determine priority based on sender or content
var priority = e.Message.From?.Address?.EndsWith("@vip.com") == true
? RelayPriority.Urgent
: RelayPriority.Normal;
// Queue with priority
await server.QueueForRelayAsync(e.Message, e.Session, priority);
};
🔄 Retry Configuration
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Maximum retry attempts
config.MaxRetryCount = 10;
// Message lifetime before expiration
config.MessageLifetime = TimeSpan.FromDays(4);
// Connection timeout per attempt
config.ConnectionTimeout = TimeSpan.FromMinutes(5);
// Queue processing interval
config.QueueProcessingInterval = TimeSpan.FromSeconds(30);
// Cleanup expired messages interval
config.CleanupInterval = TimeSpan.FromHours(1);
});
Retry Schedule
The relay service uses exponential backoff for retries:
- 1st retry: 1 minute
- 2nd retry: 2 minutes
- 3rd retry: 4 minutes
- 4th retry: 8 minutes
- 5th retry: 16 minutes
- 6th retry: 32 minutes
- 7th+ retry: 1-4 hours (capped)
📬 Bounce Messages
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Enable bounce message generation
config.EnableBounceMessages = true;
// Set bounce sender address
config.BounceSender = "postmaster@mydomain.com";
// Enable delivery status notifications
config.EnableDsn = true;
});
🔐 Authentication Methods
AUTH PLAIN
var smartHost = new SmartHostConfiguration
{
Host = "smtp.example.com",
Port = 587,
Credentials = new NetworkCredential("username", "password"),
UseStartTls = true
};
AUTH LOGIN
The relay client automatically detects and uses the appropriate authentication method based on server capabilities.
📈 Load Balancing
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Configure multiple smart hosts with weights
config.SmartHosts.AddRange(new[]
{
new SmartHostConfiguration
{
Host = "smtp1.example.com",
Port = 25,
Priority = 10,
Weight = 50 // 50% of traffic
},
new SmartHostConfiguration
{
Host = "smtp2.example.com",
Port = 25,
Priority = 10,
Weight = 30 // 30% of traffic
},
new SmartHostConfiguration
{
Host = "smtp3.example.com",
Port = 25,
Priority = 10,
Weight = 20 // 20% of traffic
}
});
});
🌐 TLS/SSL Configuration
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay(config =>
{
// Enable TLS for outbound connections
config.EnableTls = true;
// Require TLS (fail if not available)
config.RequireTls = true;
// Configure SSL protocols
config.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
// Validate server certificates
config.ValidateServerCertificate = true;
});
🎛️ Extension Methods
// Create server first
var server = SmtpServerBuilder
.CreateBasic()
.EnableRelay();
// Add smart host
server.AddSmartHost("smtp.gmail.com", 587,
new NetworkCredential("user", "pass"));
// Set relay domains
server.SetRelayDomains("external.com", "partner.org");
// Set local domains (not relayed)
server.SetLocalDomains("mydomain.com", "internal.local");
// Add relay network
server.AddRelayNetwork(IPAddress.Parse("192.168.1.0"));
// Get relay statistics
var stats = await server.GetRelayStatisticsAsync();
// Get relay service
var relayService = server.GetRelayService();
🔍 Message Status
| Status | Description |
|---|---|
| Queued | Message is waiting for delivery |
| InProgress | Message is currently being delivered |
| Delivered | Message successfully delivered |
| Failed | Permanent delivery failure |
| Deferred | Temporary failure, will retry |
| Expired | Message exceeded lifetime |
| Cancelled | Message was cancelled |
| PartiallyDelivered | Some recipients succeeded |
📊 Monitoring
// Get comprehensive statistics
var stats = await relayService.Queue.GetStatisticsAsync();
Console.WriteLine($"Total Messages: {stats.TotalMessages}");
Console.WriteLine($"Queued: {stats.QueuedMessages}");
Console.WriteLine($"In Progress: {stats.InProgressMessages}");
Console.WriteLine($"Deferred: {stats.DeferredMessages}");
Console.WriteLine($"Delivered: {stats.DeliveredMessages}");
Console.WriteLine($"Failed: {stats.FailedMessages}");
Console.WriteLine($"Expired: {stats.ExpiredMessages}");
Console.WriteLine($"Total Size: {stats.TotalSize} bytes");
Console.WriteLine($"Oldest Message: {stats.OldestMessageTime}");
Console.WriteLine($"Average Queue Time: {stats.AverageQueueTime}");
Console.WriteLine($"Average Retry Count: {stats.AverageRetryCount}");
// Messages by priority
foreach (var kvp in stats.MessagesByPriority)
{
Console.WriteLine($"Priority {kvp.Key}: {kvp.Value} messages");
}
// Messages by smart host
foreach (var kvp in stats.MessagesBySmartHost)
{
Console.WriteLine($"Host {kvp.Key}: {kvp.Value} messages");
}
🚀 Performance Tips
- DNS Caching - Cache MX record lookups
- Connection Pooling - Reuse SMTP client connections
- Message Batching - Group messages to same destination
- Queue Persistence - Consider persistent queue for reliability
- Smart Host Selection - Use priority and weight for optimal routing
- Concurrent Deliveries - Adjust
MaxConcurrentDeliveriesbased on resources
📚 Best Practices
- Log Relay Activity - Audit trail for compliance
- Implement Rate Limiting - Prevent abuse of relay
- Monitor Queue Size - Prevent unbounded growth
- Use TLS When Possible - Secure message transmission
- Configure Bounce Handling - Inform senders of failures
- Regular Cleanup - Remove expired messages periodically
- Set Message Lifetime - Clean up undeliverable messages
- Always Configure Timeouts - Prevent hanging connections
🔒 Security Considerations
- Regular security audits
- Monitor for relay abuse
- Implement rate limiting
- Validate server certificates
- Limit relay networks to trusted IPs
- Use TLS/SSL for all outbound connections
- Always require authentication for relay access
📋 Requirements
- Windows, Linux, or macOS
- .NET 6.0, 7.0, 8.0, 9.0, or 10.0
- Zetian SMTP Server package
📚 Documentation & Support
- Issues: GitHub Issues
- Examples: GitHub Examples
- Discussions: GitHub Discussions
- Documentation: Zetian Documentation
📄 License
MIT License - see LICENSE
Built with ❤️ for the .NET community
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. 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 is compatible. 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
All changes are detailed at https://zetian.soferity.com/changelog.