diff --git a/Src/SmtpServer/ISessionServiceProviderFactory.cs b/Src/SmtpServer/ISessionServiceProviderFactory.cs new file mode 100644 index 0000000..aeb7ae0 --- /dev/null +++ b/Src/SmtpServer/ISessionServiceProviderFactory.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading.Tasks; + +namespace SmtpServer +{ + /// + /// Allows customization of the IServiceProvider instance that is used in the session context. + /// + public interface ISessionServiceProviderFactory + { + /// + /// Creates an IServiceProvider instance for one session context. + /// + IServiceProvider CreateServiceProvider(IServiceProvider rootServiceProvider); + } +} diff --git a/Src/SmtpServer/Net/IEndpointListener.cs b/Src/SmtpServer/Net/IEndpointListener.cs index 11a287b..ef3b958 100644 --- a/Src/SmtpServer/Net/IEndpointListener.cs +++ b/Src/SmtpServer/Net/IEndpointListener.cs @@ -11,7 +11,7 @@ namespace SmtpServer.Net public interface IEndpointListener : IDisposable { /// - /// Returns a securtable pipe to the endpoint. + /// Returns a securable pipe to the endpoint. /// /// The session context that the pipe is being created for. /// The cancellation token. diff --git a/Src/SmtpServer/SmtpServer.cs b/Src/SmtpServer/SmtpServer.cs index d4c4a75..686819e 100644 --- a/Src/SmtpServer/SmtpServer.cs +++ b/Src/SmtpServer/SmtpServer.cs @@ -35,6 +35,7 @@ public class SmtpServer readonly ISmtpServerOptions _options; readonly IServiceProvider _serviceProvider; readonly IEndpointListenerFactory _endpointListenerFactory; + readonly ISessionServiceProviderFactory _sessionServiceProviderFactory; readonly SmtpSessionManager _sessions; readonly CancellationTokenSource _shutdownTokenSource = new CancellationTokenSource(); readonly TaskCompletionSource _shutdownTask = new TaskCompletionSource(); @@ -50,6 +51,7 @@ public SmtpServer(ISmtpServerOptions options, IServiceProvider serviceProvider) _serviceProvider = serviceProvider; _sessions = new SmtpSessionManager(this); _endpointListenerFactory = serviceProvider.GetServiceOrDefault(EndpointListenerFactory.Default); + _sessionServiceProviderFactory = serviceProvider.GetServiceOrDefault(null); } /// @@ -128,7 +130,8 @@ async Task ListenAsync(IEndpointDefinition endpointDefinition, CancellationToken while (cancellationTokenSource.Token.IsCancellationRequested == false) { - var sessionContext = new SmtpSessionContext(_serviceProvider, _options, endpointDefinition); + var spForCtx = _sessionServiceProviderFactory?.CreateServiceProvider(_serviceProvider); + var sessionContext = new SmtpSessionContext(spForCtx ?? _serviceProvider, _options, endpointDefinition); try { @@ -144,7 +147,7 @@ async Task ListenAsync(IEndpointDefinition endpointDefinition, CancellationToken if (sessionContext.Pipe != null) { - _sessions.Run(sessionContext, cancellationTokenSource.Token); + _sessions.Run(sessionContext, cancellationTokenSource.Token, spForCtx); } } } diff --git a/Src/SmtpServer/SmtpSessionManager.cs b/Src/SmtpServer/SmtpSessionManager.cs index d490028..e5f462b 100644 --- a/Src/SmtpServer/SmtpSessionManager.cs +++ b/Src/SmtpServer/SmtpSessionManager.cs @@ -16,9 +16,9 @@ internal SmtpSessionManager(SmtpServer smtpServer) _smtpServer = smtpServer; } - internal void Run(SmtpSessionContext sessionContext, CancellationToken cancellationToken) + internal void Run(SmtpSessionContext sessionContext, CancellationToken cancellationToken, IServiceProvider sessionServiceProvider) { - var handle = new SmtpSessionHandle(new SmtpSession(sessionContext), sessionContext); + var handle = new SmtpSessionHandle(new SmtpSession(sessionContext), sessionContext, sessionServiceProvider); Add(handle); handle.CompletionTask = RunAsync(handle, cancellationToken).ContinueWith(task => @@ -27,7 +27,7 @@ internal void Run(SmtpSessionContext sessionContext, CancellationToken cancellat }); } - async Task RunAsync(SmtpSessionHandle handle, CancellationToken cancellationToken) + private async Task RunAsync(SmtpSessionHandle handle, CancellationToken cancellationToken) { using var sessionTimeoutCancellationTokenSource = new CancellationTokenSource(handle.SessionContext.EndpointDefinition.SessionTimeout); @@ -58,6 +58,15 @@ async Task RunAsync(SmtpSessionHandle handle, CancellationToken cancellationToke await handle.SessionContext.Pipe.Input.CompleteAsync(); handle.SessionContext.Pipe.Dispose(); + + if (handle.SessionServiceProvider is IAsyncDisposable asyncDisposable) + { + await asyncDisposable.DisposeAsync(); + } + else if (handle.SessionServiceProvider is IDisposable disposable) + { + disposable.Dispose(); + } } } @@ -91,16 +100,19 @@ void Remove(SmtpSessionHandle handle) class SmtpSessionHandle { - public SmtpSessionHandle(SmtpSession session, SmtpSessionContext sessionContext) + public SmtpSessionHandle(SmtpSession session, SmtpSessionContext sessionContext, IServiceProvider sessionServiceProvider) { Session = session; SessionContext = sessionContext; + SessionServiceProvider = sessionServiceProvider; } public SmtpSession Session { get; } public SmtpSessionContext SessionContext { get; } + public IServiceProvider SessionServiceProvider { get; } + public Task CompletionTask { get; set; } } }