Giter VIP home page Giter VIP logo

csharp-smtp-server's Introduction

CSharp-SMTP-Server GitHub release NuGet License

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

csharp-smtp-server's People

Contributors

zabszk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

csharp-smtp-server's Issues

No Subject in Email Messages.

The IMessageTransaction interface and implementations do not implement Subject and the underlying server code does not parse the subject of the email.

Linux support?

Hi everyone,

I'm trying to use this library in a docker container on Linux.

the library is starting successful but when it comes to receive a mail it's throwing this exception:

[Client receive loop] Exception: System.IndexOutOfRangeException, Index was outside the bounds of the array.

Any Idea?

Thanks in advance

Email messages missing CC addresses.

The IMessageTransaction interface and implementations do not implement CC and the underlying server code does not parse the CC addresses of the email. Instead the address are added to the To address collection.

Email messages missing BCC addresses.

The IMessageTransaction interface and implementations do not implement BCC and the underlying server code does not parse the BCC addresses of the email. Instead the address are added to the To address collection.

Could not load type 'DnsClient.DnsClientOptions' while using Couchbase

I'm using Couchbase as database. Couchbase requires the nuget Packet "DnsClient", your CSharp-SMTP-Server requires your zabszk/DnsClient. Both have the namespace of "DnsClient". That way either one (Couchbase or CSharp-SMTP-Server) will always error out.

A possible fix would be to move the DnsClient into a namespace prefixed with zabszk.

Unhandled exception. System.TypeLoadException: Could not load type 'DnsClient.DnsClientOptions' from assembly 'DnsClient, Version=1.3.2.0, Culture=neutral, PublicKeyToken=4574bb5573c51424'.
   at CSharp_SMTP_Server.SMTPServer..ctor(IEnumerable`1 parameters, ServerOptions options, IMailDelivery deliveryInterface, ILogger loggerInterface, X509Certificate certificate)
   at MailserverTest.Program.Main(String[] args) in E:\Personal\evolin\MailserverTest\MailserverTest\Program.cs:line 19
   at MailserverTest.Program.<Main>(String[] args)
Aborted (core dumped)

[Client receive loop] Exception: System.ArgumentOutOfRangeException, Length cannot be less than zero. (Parameter 'length')

Issue Description:
When our application is receiving an email from an Exchange Server, it throws the following exception:

[Client receive loop] Exception: System.ArgumentOutOfRangeException, Length cannot be less than zero. (Parameter 'length').

This issue persists even if the SPF check is disabled. Unfortunately, we do not have more detailed information at this time, and it appears to be related to SPF checks or email handling.

Steps to Reproduce:

  1. Receive an email from an Exchange Server.
  2. Observe the application's behavior.

Expected Behavior:
The application should handle incoming emails from the Exchange Server without any exceptions.

Actual Behavior:
The application throws a System.ArgumentOutOfRangeException exception with the message "Length cannot be less than zero."

Additional Information:

  • The issue appears to be related to SPF checks or email handling, but more specific information about the cause of the problem is not available.
  • This issue might be related to the specific content or structure of emails received from the Exchange Server, but we need assistance in diagnosing and resolving it.

Environment:

  • Application version: 1.1.5
  • Operating System: Linux and Windows
  • .NET Framework version: net7.0

Steps Taken to Resolve:

  • We have already disabled SPF checks to see if it resolves the issue, but it persists.
  • Reviewed logs and code for potential issues, but the root cause is unclear.

Email messages missing attachments.

The IMessageTransaction interface and implementations do not implement an Attachment collection and the underlying server code does not parse the attachments of the email.

Nuget Package

Hey,

Would you mind setting this up as a Nuget package?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.