/// <inheritdoc/> public async Task Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage == null) { await connection.WriteResponse(new SmtpResponse( StandardSmtpResponseCode.BadSequenceOfCommands, "No current message")).ConfigureAwait(false); return; } if (command.ArgumentsText == "<>" || !command.ArgumentsText.StartsWith("<", StringComparison.Ordinal) || !command.ArgumentsText.EndsWith(">", StringComparison.Ordinal) || command.ArgumentsText.Count(c => c == '<') != command.ArgumentsText.Count(c => c == '>')) { await connection.WriteResponse( new SmtpResponse( StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify to address <address>")).ConfigureAwait(false); return; } string address = command.ArgumentsText.Remove(0, 1).Remove(command.ArgumentsText.Length - 2); await connection.Server.Behaviour.OnMessageRecipientAdding(connection, connection.CurrentMessage, address).ConfigureAwait(false); connection.CurrentMessage.Recipients.Add(address); await connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Recipient accepted")).ConfigureAwait(false); }
public void Process(IConnection connection, SmtpCommand command) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.ClosingTransmissionChannel, "See you later aligator")); connection.CloseConnection(); connection.Session.CompletedNormally = true; }
public async Task ProcessAsync(IConnection connection, SmtpCommand command) { await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.ClosingTransmissionChannel, "Goodbye")); await connection.CloseConnectionAsync(); connection.Session.CompletedNormally = true; }
public virtual void Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage == null) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "Bad sequence of commands")); return; } connection.CurrentMessage.SecureConnection = connection.Session.SecureConnection; connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.StartMailInputEndWithDot, "End message with period")); using (StreamWriter writer = new StreamWriter(connection.CurrentMessage.GetData(DataAccessMode.ForWriting), connection.ReaderEncoding)) { bool firstLine = true; do { string line = connection.ReadLine(); if (line != ".") { line = ProcessLine(line); if (!firstLine) writer.Write(Environment.NewLine); writer.Write(line); } else { break; } firstLine = false; } while (true); writer.Flush(); long? maxMessageSize = connection.Server.Behaviour.GetMaximumMessageSize(connection); if (maxMessageSize.HasValue && writer.BaseStream.Length > maxMessageSize.Value) { connection.WriteResponse( new SmtpResponse(StandardSmtpResponseCode.ExceededStorageAllocation, "Message exceeds fixed size limit")); } else { writer.Close(); connection.Server.Behaviour.OnMessageCompleted(connection); connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Mail accepted")); connection.CommitMessage(); } } }
public virtual void Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage == null) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "Bad sequence of commands")); return; } connection.CurrentMessage.SecureConnection = connection.Session.SecureConnection; connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.StartMailInputEndWithDot, "End message with period")); using (StreamWriter writer = new StreamWriter(connection.CurrentMessage.WriteData(), connection.ReaderEncoding)) { bool firstLine = true; do { string line = connection.ReadLine(); if (line != ".") { line = ProcessLine(line); if (!firstLine) { writer.Write(Environment.NewLine); } writer.Write(line); } else { break; } firstLine = false; } while (true); writer.Flush(); long?maxMessageSize = connection.Server.Behaviour.GetMaximumMessageSize(connection); if (maxMessageSize.HasValue && writer.BaseStream.Length > maxMessageSize.Value) { connection.WriteResponse( new SmtpResponse(StandardSmtpResponseCode.ExceededStorageAllocation, "Message exceeds fixed size limit")); } else { writer.Close(); connection.Server.Behaviour.OnMessageCompleted(connection); connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Mail accepted")); connection.CommitMessage(); } } }
/// <inheritdoc/> public async Task Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage != null) { await connection.WriteResponse(new SmtpResponse( StandardSmtpResponseCode.BadSequenceOfCommands, "You already told me who the message was from")).ConfigureAwait(false); return; } if (command.ArgumentsText.Length == 0) { await connection.WriteResponse( new SmtpResponse( StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify from address or <>")).ConfigureAwait(false); return; } ArgumentsParser argumentsParser = new ArgumentsParser(command.ArgumentsText); System.Collections.Generic.IReadOnlyCollection <string> arguments = argumentsParser.Arguments; string from = arguments.First(); if (from.StartsWith("<", StringComparison.OrdinalIgnoreCase)) { from = from.Remove(0, 1); } if (from.EndsWith(">", StringComparison.OrdinalIgnoreCase)) { from = from.Remove(from.Length - 1, 1); } await connection.Server.Behaviour.OnMessageStart(connection, from).ConfigureAwait(false); await connection.NewMessage().ConfigureAwait(false); connection.CurrentMessage.ReceivedDate = this.currentDateTimeProvider.GetCurrentDateTime(); connection.CurrentMessage.From = from; try { await this.ParameterProcessorMap.Process(connection, arguments.Skip(1).ToArray(), true).ConfigureAwait(false); await connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "New message started")).ConfigureAwait(false); } catch { await connection.AbortMessage().ConfigureAwait(false); throw; } }
public async Task ProcessAsync(IConnection connection, SmtpCommand command) { if (!string.IsNullOrEmpty(connection.Session.ClientName)) { await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already said HELO")); return; } connection.Session.ClientName = command.ArgumentsText ?? ""; await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.OK, "Nice to meet you")); }
public void Process(IConnection connection, SmtpCommand command) { if (!string.IsNullOrEmpty(connection.Session.ClientName)) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already said HELO")); return; } connection.Session.ClientName = command.Arguments[0]; connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Nice to meet you")); }
public void Process(IConnection connection, SmtpCommand command) { if (!string.IsNullOrEmpty(connection.Session.ClientName)) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already said HELO")); return; } connection.Session.ClientName = command.ArgumentsText ?? ""; connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Nice to meet you")); }
public async Task ProcessAsync(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage != null) { await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already told me who the message was from")); return; } if (command.ArgumentsText.Length == 0) { await connection.WriteResponseAsync( new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify from address or <>")); return; } ArgumentsParser argumentsParser = new ArgumentsParser(command.ArgumentsText); string[] arguments = argumentsParser.Arguments; string from = arguments.First(); if (from.StartsWith("<")) { from = from.Remove(0, 1); } if (from.EndsWith(">")) { from = from.Remove(from.Length - 1, 1); } connection.Server.Behaviour.OnMessageStart(connection, from); connection.NewMessage(); connection.CurrentMessage.ReceivedDate = _currentDateTimeProvider.GetCurrentDateTime(); connection.CurrentMessage.From = from; try { await ParameterProcessorMap.ProcessAsync(connection, arguments.Skip(1).ToArray(), true); await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.OK, "New message started")); } catch { connection.AbortMessage(); throw; } }
/// <inheritdoc/> public async Task Process(IConnection connection, SmtpCommand command) { if (!string.IsNullOrEmpty(connection.Session.ClientName)) { await connection.WriteResponse(new SmtpResponse( StandardSmtpResponseCode.BadSequenceOfCommands, "You already said HELO")).ConfigureAwait(false); return; } connection.Session.ClientName = command.ArgumentsText ?? string.Empty; await connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Nice to meet you")).ConfigureAwait(false); }
public void Process(IConnection connection, SmtpCommand command) { SmtpCommand subrequest = new SmtpCommand(command.ArgumentsText); IVerb verbProcessor = SubVerbMap.GetVerbProcessor(subrequest.Verb); if (verbProcessor != null) { verbProcessor.Process(connection, subrequest); } else { connection.WriteResponse( new SmtpResponse(StandardSmtpResponseCode.CommandParameterNotImplemented, "Subcommand {0} not implemented", subrequest.Verb)); } }
public void Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage != null) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already told me who the message was from")); return; } if (command.ArgumentsText.Length == 0) { connection.WriteResponse( new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify from address or <>")); return; } string from = command.Arguments.First(); if (from.StartsWith("<")) { from = from.Remove(0, 1); } if (from.EndsWith(">")) { from = from.Remove(from.Length - 1, 1); } connection.Server.Behaviour.OnMessageStart(connection, from); connection.NewMessage(); connection.CurrentMessage.From = from; try { ParameterProcessorMap.Process(command.Arguments.Skip(1).ToArray(), true); connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Okey dokey")); } catch { connection.AbortMessage(); throw; } }
/// <inheritdoc/> public async Task Process(IConnection connection, SmtpCommand command) { SmtpCommand subrequest = new SmtpCommand(command.ArgumentsText); IVerb verbProcessor = this.SubVerbMap.GetVerbProcessor(subrequest.Verb); if (verbProcessor != null) { await verbProcessor.Process(connection, subrequest).ConfigureAwait(false); } else { await connection.WriteResponse( new SmtpResponse( StandardSmtpResponseCode.CommandParameterNotImplemented, "Subcommand {0} not implemented", subrequest.Verb)).ConfigureAwait(false); } }
/// <inheritdoc/> public async Task Process(IConnection connection, SmtpCommand command) { connection.Session.ClientName = command.ArgumentsText ?? string.Empty; SmtpStringBuilder text = new SmtpStringBuilder(); text.AppendLine("Nice to meet you."); foreach (Extensions.IExtensionProcessor extensionProcessor in connection.ExtensionProcessors) { foreach (string ehloKeyword in await extensionProcessor.GetEHLOKeywords().ConfigureAwait(false)) { text.AppendLine(ehloKeyword); } } await connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, text.ToString().TrimEnd())).ConfigureAwait(false); }
public async Task ProcessAsync(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage != null) { await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already told me who the message was from")); return; } if (command.ArgumentsText.Length == 0) { await connection.WriteResponseAsync( new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify from address or <>")); return; } ArgumentsParser argumentsParser = new ArgumentsParser(command.ArgumentsText); string[] arguments = argumentsParser.Arguments; string from = arguments.First(); if (from.StartsWith("<")) from = from.Remove(0, 1); if (from.EndsWith(">")) from = from.Remove(from.Length - 1, 1); connection.Server.Behaviour.OnMessageStart(connection, from); connection.NewMessage(); connection.CurrentMessage.ReceivedDate = _currentDateTimeProvider.GetCurrentDateTime(); connection.CurrentMessage.From = from; try { await ParameterProcessorMap.ProcessAsync(connection, arguments.Skip(1).ToArray(), true); await connection.WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.OK, "New message started")); } catch { connection.AbortMessage(); throw; } }
public void Process(IConnection connection, SmtpCommand command) { if (!string.IsNullOrEmpty(connection.Session.ClientName)) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already said HELO")); return; } StringBuilder text = new StringBuilder(); text.AppendLine("Nice to meet you."); foreach (string extnName in connection.ExtensionProcessors.SelectMany(extn => extn.EHLOKeywords)) { text.AppendLine(extnName); } connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, text.ToString().TrimEnd())); }
public void Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage != null) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "You already told me who the message was from")); return; } if (command.ArgumentsText.Length == 0) { connection.WriteResponse( new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify from address or <>")); return; } string from = command.Arguments.First(); if (from.StartsWith("<")) from = from.Remove(0, 1); if (from.EndsWith(">")) from = from.Remove(from.Length - 1, 1); connection.Server.Behaviour.OnMessageStart(connection, from); connection.NewMessage(); connection.CurrentMessage.From = from; try { ParameterProcessorMap.Process(command.Arguments.Skip(1).ToArray(), true); connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Okey dokey")); } catch { connection.AbortMessage(); throw; } }
public void Process(IConnection connection, SmtpCommand command) { if (connection.CurrentMessage == null) { connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.BadSequenceOfCommands, "No current message")); return; } if (command.ArgumentsText == "<>" || !command.ArgumentsText.StartsWith("<") || !command.ArgumentsText.EndsWith(">") || command.ArgumentsText.Count(c => c == '<') != command.ArgumentsText.Count(c => c == '>')) { connection.WriteResponse( new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "Must specify to address <address>")); return; } string address = command.ArgumentsText.Remove(0, 1).Remove(command.ArgumentsText.Length - 2); connection.Server.Behaviour.OnMessageRecipientAdding(connection, connection.CurrentMessage, address); connection.CurrentMessage.ToList.Add(address); connection.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.OK, "Recipient accepted")); }
public void Process() { Thread = System.Threading.Thread.CurrentThread; try { Server.Behaviour.OnSessionStarted(this, Session); SetReaderEncoding(Server.Behaviour.GetDefaultEncoding(this)); if (Server.Behaviour.IsSSLEnabled(this)) { ConnectionChannel.ApplyStreamFilter(s => { SslStream sslStream = new SslStream(s); sslStream.AuthenticateAsServer(Server.Behaviour.GetSSLCertificate(this)); return sslStream; }); Session.SecureConnection = true; } WriteResponse(new SmtpResponse(StandardSmtpResponseCode.ServiceReady, Server.Behaviour.DomainName + " smtp4dev ready")); int numberOfInvalidCommands = 0; while (ConnectionChannel.IsConnected) { bool badCommand = false; SmtpCommand command = new SmtpCommand(ReadLine()); Server.Behaviour.OnCommandReceived(this, command); if (command.IsValid) { IVerb verbProcessor = VerbMap.GetVerbProcessor(command.Verb); if (verbProcessor != null) { try { verbProcessor.Process(this, command); } catch (SmtpServerException exception) { WriteResponse(exception.SmtpResponse); } } else { badCommand = true; } } else if (command.IsEmpty) { } else { badCommand = true; } if (badCommand) { numberOfInvalidCommands++; if (Server.Behaviour.MaximumNumberOfSequentialBadCommands > 0 && numberOfInvalidCommands >= Server.Behaviour.MaximumNumberOfSequentialBadCommands) { WriteResponse(new SmtpResponse(StandardSmtpResponseCode.ClosingTransmissionChannel, "Too many bad commands. Bye!")); CloseConnection(); } else { WriteResponse(new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorCommandUnrecognised, "Command unrecognised")); } } } } catch (IOException ioException) { Session.SessionError = ioException; Session.SessionErrorType = SessionErrorType.NetworkError; } catch (ThreadInterruptedException exception) { Session.SessionError = exception; Session.SessionErrorType = SessionErrorType.ServerShutdown; } catch (Exception exception) { Session.SessionError = exception; Session.SessionErrorType = SessionErrorType.UnexpectedException; } CloseConnection(); Session.EndDate = DateTime.Now; Server.Behaviour.OnSessionCompleted(this, Session); }
public void Start() { try { Server.Behaviour.OnSessionStarted(this, Session); if (Server.Behaviour.IsSSLEnabled(this)) { SslStream sslStream = new SslStream(_stream); sslStream.AuthenticateAsServer(Server.Behaviour.GetSSLCertificate(this)); Session.SecureConnection = true; _stream = sslStream; SetupReaderAndWriter(); } WriteResponse(new SmtpResponse(StandardSmtpResponseCode.ServiceReady, Server.Behaviour.DomainName + " smtp4dev ready")); while (_tcpClient.Client.Connected) { SmtpCommand command = new SmtpCommand(ReadLine()); Server.Behaviour.OnCommandReceived(this, command); if (command.IsValid) { IVerb verbProcessor = VerbMap.GetVerbProcessor(command.Verb); if (verbProcessor != null) { try { verbProcessor.Process(this, command); } catch (SmtpServerException exception) { WriteResponse(exception.SmtpResponse); } } else { WriteResponse(new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorCommandUnrecognised, "Command unrecognized")); } } else if (command.IsEmpty) { } else { WriteResponse(new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorCommandUnrecognised, "Command unrecognized")); } } } catch (IOException ioException) { Session.SessionError = ioException.Message; } CloseConnection(); Session.EndDate = DateTime.Now; Server.Behaviour.OnSessionCompleted(this, Session); }
public CommandEventArgs(SmtpCommand command) { Command = command; }
public void OnCommandReceived(IConnection connection, SmtpCommand command) { }
/// <inheritdoc/> public virtual Task OnCommandReceived(IConnection connection, SmtpCommand command) { this.CommandReceivedEventHandler?.Invoke(this, new CommandEventArgs(command)); return(Task.CompletedTask); }
/// <summary> /// Starts processing of this connection. /// </summary> /// <returns>A <see cref="Task{T}"/> representing the async operation.</returns> internal async Task ProcessAsync() { try { await this.Server.Behaviour.OnSessionStarted(this, this.Session).ConfigureAwait(false); if (await this.Server.Behaviour.IsSSLEnabled(this).ConfigureAwait(false)) { await this.ConnectionChannel.ApplyStreamFilter(async s => { SslStream sslStream = new SslStream(s); await sslStream.AuthenticateAsServerAsync(await this.Server.Behaviour.GetSSLCertificate(this).ConfigureAwait(false)).ConfigureAwait(false); return(sslStream); }).ConfigureAwait(false); this.Session.SecureConnection = true; } await this.WriteResponse(new SmtpResponse( StandardSmtpResponseCode.ServiceReady, this.Server.Behaviour.DomainName + " smtp4dev ready")).ConfigureAwait(false); int numberOfInvalidCommands = 0; while (this.ConnectionChannel.IsConnected) { bool badCommand = false; SmtpCommand command = new SmtpCommand(await this.ReadLine().ConfigureAwait(false)); await this.Server.Behaviour.OnCommandReceived(this, command).ConfigureAwait(false); if (command.IsValid) { IVerb verbProcessor = this.VerbMap.GetVerbProcessor(command.Verb); if (verbProcessor != null) { try { await verbProcessor.Process(this, command).ConfigureAwait(false); } catch (SmtpServerException exception) { await this.WriteResponse(exception.SmtpResponse).ConfigureAwait(false); } } else { badCommand = true; } } else if (command.IsEmpty) { } else { badCommand = true; } if (badCommand) { numberOfInvalidCommands++; if (this.Server.Behaviour.MaximumNumberOfSequentialBadCommands > 0 && numberOfInvalidCommands >= this.Server.Behaviour.MaximumNumberOfSequentialBadCommands) { await this.WriteResponse(new SmtpResponse(StandardSmtpResponseCode.ClosingTransmissionChannel, "Too many bad commands. Bye!")).ConfigureAwait(false); await this.CloseConnection().ConfigureAwait(false); } else { await this.WriteResponse(new SmtpResponse( StandardSmtpResponseCode.SyntaxErrorCommandUnrecognised, "Command unrecognised")).ConfigureAwait(false); } } } } catch (IOException ioException) { this.Session.SessionError = ioException; this.Session.SessionErrorType = SessionErrorType.NetworkError; } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception exception) { this.Session.SessionError = exception; this.Session.SessionErrorType = SessionErrorType.UnexpectedException; } #pragma warning restore CA1031 // Do not catch general exception types await this.CloseConnection().ConfigureAwait(false); this.Session.EndDate = DateTime.Now; await this.Server.Behaviour.OnSessionCompleted(this, this.Session).ConfigureAwait(false); }
public virtual void OnCommandReceived(IConnection connection, SmtpCommand command) { if (CommandReceived != null) { CommandReceived(this, new CommandEventArgs(command)); } }
public async Task ProcessAsync() { try { Server.Behaviour.OnSessionStarted(this, Session); SetReaderEncoding(Server.Behaviour.GetDefaultEncoding(this)); if (Server.Behaviour.IsSSLEnabled(this)) { await ConnectionChannel.ApplyStreamFilterAsync(async s => { SslStream sslStream = new SslStream(s); await sslStream.AuthenticateAsServerAsync(Server.Behaviour.GetSSLCertificate(this)); return(sslStream); }); Session.SecureConnection = true; } await WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.ServiceReady, Server.Behaviour.DomainName + " smtp4dev ready")); int numberOfInvalidCommands = 0; while (ConnectionChannel.IsConnected) { bool badCommand = false; SmtpCommand command = new SmtpCommand(await ReadLineAsync()); Server.Behaviour.OnCommandReceived(this, command); if (command.IsValid) { IVerb verbProcessor = VerbMap.GetVerbProcessor(command.Verb); if (verbProcessor != null) { try { await verbProcessor.ProcessAsync(this, command); } catch (SmtpServerException exception) { await WriteResponseAsync(exception.SmtpResponse); } } else { badCommand = true; } } else if (command.IsEmpty) { } else { badCommand = true; } if (badCommand) { numberOfInvalidCommands++; if (Server.Behaviour.MaximumNumberOfSequentialBadCommands > 0 && numberOfInvalidCommands >= Server.Behaviour.MaximumNumberOfSequentialBadCommands) { await WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.ClosingTransmissionChannel, "Too many bad commands. Bye!")); await CloseConnectionAsync(); } else { await WriteResponseAsync(new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorCommandUnrecognised, "Command unrecognised")); } } } } catch (IOException ioException) { Session.SessionError = ioException; Session.SessionErrorType = SessionErrorType.NetworkError; } catch (Exception exception) { Session.SessionError = exception; Session.SessionErrorType = SessionErrorType.UnexpectedException; } await CloseConnectionAsync(); Session.EndDate = DateTime.Now; Server.Behaviour.OnSessionCompleted(this, Session); }