diff --git a/Src/SmtpServer/ISmtpServerOptions.cs b/Src/SmtpServer/ISmtpServerOptions.cs
index b0c1daa..01a6266 100644
--- a/Src/SmtpServer/ISmtpServerOptions.cs
+++ b/Src/SmtpServer/ISmtpServerOptions.cs
@@ -42,5 +42,12 @@ public interface ISmtpServerOptions
/// The size of the buffer that is read from each call to the underlying network client.
///
int NetworkBufferSize { get; }
+
+ ///
+ /// Gets the custom SMTP greeting message that the server sends immediately after a client connects,
+ /// typically as the initial "220" response. The message can be dynamically generated based on the session context.
+ /// If not set, a default greeting will be used (e.g., "220 mail.example.com ESMTP ready").
+ ///
+ Func CustomSmtpGreeting { get; }
}
}
diff --git a/Src/SmtpServer/SmtpServerOptionsBuilder.cs b/Src/SmtpServer/SmtpServerOptionsBuilder.cs
index 307ff8f..7516728 100644
--- a/Src/SmtpServer/SmtpServerOptionsBuilder.cs
+++ b/Src/SmtpServer/SmtpServerOptionsBuilder.cs
@@ -24,6 +24,7 @@ public ISmtpServerOptions Build()
MaxAuthenticationAttempts = 3,
NetworkBufferSize = 128,
CommandWaitTimeout = TimeSpan.FromMinutes(5),
+ CustomSmtpGreeting = null,
};
_setters.ForEach(setter => setter(serverOptions));
@@ -157,6 +158,23 @@ public SmtpServerOptionsBuilder CommandWaitTimeout(TimeSpan value)
return this;
}
+ ///
+ /// Sets the custom SMTP greeting message sent to the client upon connection,
+ /// typically returned as the initial "220" response.
+ ///
+ ///
+ /// A delegate that returns the greeting message to send to the client,
+ /// based on the (e.g., client IP, TLS state).
+ /// Example: ctx => $"220 {sessionContext.ServerOptions.ServerName} ESMTP ready"
+ ///
+ /// An OptionsBuilder to continue building on.
+ public SmtpServerOptionsBuilder CustomGreetingMessage(Func smtpGreetingFunc)
+ {
+ _setters.Add(options => options.CustomSmtpGreeting = smtpGreetingFunc);
+
+ return this;
+ }
+
#region SmtpServerOptions
class SmtpServerOptions : ISmtpServerOptions
@@ -200,6 +218,13 @@ class SmtpServerOptions : ISmtpServerOptions
/// The size of the buffer that is read from each call to the underlying network client.
///
public int NetworkBufferSize { get; set; }
+
+ ///
+ /// Gets or sets the custom greeting message sent by the server in response to the initial SMTP connection.
+ /// This message is returned after the client connects and before any commands are issued (e.g., "220 mail.example.com v1.0 ESMTP ready").
+ /// If not set, a default greeting will be used.
+ ///
+ public Func CustomSmtpGreeting { get; set; }
}
#endregion
diff --git a/Src/SmtpServer/SmtpSession.cs b/Src/SmtpServer/SmtpSession.cs
index 292b7f5..dfc8461 100644
--- a/Src/SmtpServer/SmtpSession.cs
+++ b/Src/SmtpServer/SmtpSession.cs
@@ -1,20 +1,21 @@
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using SmtpServer.Protocol;
-using System.Reflection;
+using SmtpServer.ComponentModel;
using SmtpServer.IO;
-using System.IO.Pipelines;
+using SmtpServer.Protocol;
using SmtpServer.StateMachine;
-using SmtpServer.ComponentModel;
+using System;
using System.Buffers;
using System.Collections.Generic;
+using System.IO.Pipelines;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
namespace SmtpServer
{
internal sealed class SmtpSession
{
const string BufferKey = "SmtpSession:Buffer";
+ static readonly Version AssemblyVersion = typeof(SmtpSession).GetTypeInfo().Assembly.GetName().Version;
readonly SmtpStateMachine _stateMachine;
readonly SmtpSessionContext _context;
@@ -188,9 +189,15 @@ static async Task ExecuteAsync(SmtpCommand command, SmtpSessionContext con
/// A task which performs the operation.
ValueTask OutputGreetingAsync(CancellationToken cancellationToken)
{
- var version = typeof(SmtpSession).GetTypeInfo().Assembly.GetName().Version;
-
- _context.Pipe.Output.WriteLine($"220 {_context.ServerOptions.ServerName} v{version} ESMTP ready");
+ if (_context.ServerOptions.CustomSmtpGreeting is null)
+ {
+ var serverVersion = AssemblyVersion;
+ _context.Pipe.Output.WriteLine($"220 {_context.ServerOptions.ServerName} v{serverVersion} ESMTP ready");
+ }
+ else
+ {
+ _context.Pipe.Output.WriteLine(_context.ServerOptions.CustomSmtpGreeting(_context));
+ }
return _context.Pipe.Output.FlushAsync(cancellationToken);
}