CSharp-SMTP-Server
1.1.6
.NET 6.0
This package targets .NET 6.0. The package is compatible with this framework or higher.
.NET Standard 2.1
This package targets .NET Standard 2.1. The package is compatible with this framework or higher.
dotnet add package CSharp-SMTP-Server --version 1.1.6
NuGet\Install-Package CSharp-SMTP-Server -Version 1.1.6
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="CSharp-SMTP-Server" Version="1.1.6" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add CSharp-SMTP-Server --version 1.1.6
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: CSharp-SMTP-Server, 1.1.6"
#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.
// Install CSharp-SMTP-Server as a Cake Addin #addin nuget:?package=CSharp-SMTP-Server&version=1.1.6 // Install CSharp-SMTP-Server as a Cake Tool #tool nuget:?package=CSharp-SMTP-Server&version=1.1.6
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
CSharp-SMTP-Server
Simple (receive only) SMTP server library for C#.
This server is only returning all received emails to interface provided by the software running this library.
Supported features
- TLS and STARTTLS
- AUTH LOGIN and AUTH PLAIN
Compatible with
- RFC 822 (STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES)
- RFC 1869 (SMTP Service Extensions)
- RFC 2554 (SMTP Service Extension for Authentication)
- RFC 3463 (Enhanced Mail System Status Codes)
- RFC 4616 (The PLAIN Simple Authentication and Security Layer (SASL) Mechanism)
- RFC 4954 (SMTP Service Extension for Authentication)
- RFC 5321 (SMTP Protocol)
- RFC 7208 (Sender Policy Framework)
- RFC 7372 (Email Authentication Status Codes)
- RFC 7489 (Domain-based Message Authentication, Reporting, and Conformance (DMARC)) [Partially Supported]
3rd party services and libraries usage
- This library by default uses Cloudflare Public DNS Servers (1.1.1.1) to perform SPF and DMARC validation. IP address of the DNS server can be changed or both validations can be disabled using ServerOptions class.
- This library by default downloads Public Suffix List managed by Mozilla Foundation from GitHub. The list is licensed under Mozilla Public License v. 2.0. The download URL can be changed in ServerOptions class. The list is NOT downloaded if DnsServerEndpoint is set to null in ServerOptions class.
- This library uses MimeKit library created by .NET Foundation and Contributors and licensed under The MIT License.
Basic usage
var server = new SMTPServer(new[]
{
new ListeningParameters(IPAddress.IPv6Any, new ushort[]{25, 587}, new ushort[]{465}, true)
}, new ServerOptions(){ServerName = "Test SMTP Server", RequireEncryptionForAuth = false}, new DeliveryInterface(), new LoggerInterface());
//with TLS:
//}, new ServerOptions() { ServerName = "Test SMTP Server", RequireEncryptionForAuth = true}, new DeliveryInterface(), new LoggerInterface(), new X509Certificate2("PathToCertWithKey.pfx"));
server.SetAuthLogin(new AuthenticationInterface());
server.SetFilter(new FilterInterface());
server.Start();
class LoggerInterface : ILogger
{
public void LogError(string text) => Console.WriteLine("[LOG] " + text);
}
class DeliveryInterface : IMailDelivery
{
//Let's just print all emails
public Task EmailReceived(MailTransaction transaction)
{
Console.WriteLine(
$"\n\n--- EMAIL TRANSACTION ---\nSource IP: {transaction.RemoteEndPoint}\nAuthenticated: {transaction.AuthenticatedUser ?? "(not authenticated)"}\nFrom: {transaction.From}\nTo (Commands): {transaction.DeliverTo.Aggregate((current, item) => current + ", " + item)}\nTo (Headers): {transaction.To.Aggregate((current, item) => current + ", " + item)}\nCc: {transaction.Cc.Aggregate((current, item) => current + ", " + item)}\nBcc: {transaction.Bcc.Aggregate((current, item) => current + ", " + item)}\nBody: {transaction.Body}\n--- END OF TRANSACTION ---\n\n");
return Task.CompletedTask;
}
//We only own "@smtp.demo" and we don't want any emails to other domains
public Task<UserExistsCodes> DoesUserExist(string emailAddress) => Task.FromResult(emailAddress.EndsWith("@smtp.demo", StringComparison.OrdinalIgnoreCase)
? UserExistsCodes.DestinationAddressValid
: UserExistsCodes.BadDestinationSystemAddress);
}
class AuthenticationInterface : IAuthLogin
{
//123 is password for all users (NOT SECURE, ONLY FOR DEMO PURPOSES!)
public Task<bool> AuthPlain(string authorizationIdentity, string authenticationIdentity, string password,
EndPoint remoteEndPoint,
bool secureConnection) => Task.FromResult(password == "123");
public Task<bool> AuthLogin(string login, string password, EndPoint remoteEndPoint, bool secureConnection) =>
Task.FromResult(password == "123");
}
class FilterInterface : IMailFilter
{
//Allow all connections
public Task<SmtpResult> IsConnectionAllowed(EndPoint ep) => Task.FromResult(new SmtpResult(SmtpResultType.Success));
//Let's block .invalid TLD
public Task<SmtpResult> IsAllowedSender(string source, EndPoint ep) => Task.FromResult(source.TrimEnd().EndsWith(".invalid")
? new SmtpResult(SmtpResultType.PermanentFail)
: new SmtpResult(SmtpResultType.Success));
//Let's reject Softfail as well
public Task<SmtpResult> IsAllowedSenderSpfVerified(string source, EndPoint? ep, SpfResult spfResult) => Task.FromResult(spfResult == SpfResult.Softfail
? new SmtpResult(SmtpResultType.PermanentFail)
: new
SmtpResult(SmtpResultType.Success));
//Let's block all emails to root at any domain
public Task<SmtpResult> CanDeliver(string source, string destination, bool authenticated, string username,
EndPoint ep) => Task.FromResult(destination.TrimStart().StartsWith("root@", StringComparison.OrdinalIgnoreCase)
? new SmtpResult(SmtpResultType.PermanentFail)
: new SmtpResult(SmtpResultType.Success));
//Let's blacklist word "spam"
public Task<SmtpResult> CanProcessTransaction(MailTransaction transaction) => Task.FromResult(transaction.GetMessageBody() != null && transaction.GetMessageBody()!.Contains("spam", StringComparison.OrdinalIgnoreCase)
? new SmtpResult(SmtpResultType.PermanentFail)
: new SmtpResult(SmtpResultType.Success));
}
Generating PFX from PEM keys
You can generate PFX from PEM certificate and PEM private key using openssl:
openssl pkcs12 -export -in public.pem -inkey private.pem -out CertWithKey.pfx
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. 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 was computed. 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. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | 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.
-
.NETStandard 2.1
- MimeKit (>= 4.3.0)
- zabszk.DnsClient (>= 1.0.1)
-
net6.0
- MimeKit (>= 4.3.0)
- zabszk.DnsClient (>= 1.0.1)
-
net7.0
- MimeKit (>= 4.3.0)
- zabszk.DnsClient (>= 1.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.