public async Task Accept() { // Add cancellation token to allow cancel from any point calling Dispose() _server._connectionManager.AddConnection(this); _cancellationTokenSource = new CancellationTokenSource(); Interlocked.Exchange(ref _timeoutTimestamp, DateTime.UtcNow.Add(_server.Options.LiveTimeout).Ticks); try { _stream = _client.GetStream(); if (_server.Certificate != null) { var ssl = new SslStream(_stream, false); await ssl.AuthenticateAsServerAsync(_server.Certificate); _stream = ssl; } _reader = new System.IO.StreamReader(_stream); _writer = new System.IO.StreamWriter(_stream); _writer.AutoFlush = true; Kooboo.Mail.Smtp.SmtpSession session = new Smtp.SmtpSession(this.Client.Address.ToString()); // Service ready await WriteLineAsync(session.ServiceReady().Render()); var commandline = await _reader.ReadLineAsync(); var cancellationToken = _cancellationTokenSource.Token; while (!cancellationToken.IsCancellationRequested && commandline != null) { var response = session.Command(commandline); if (response.SendResponse) { var responseline = response.Render(); await WriteLineAsync(responseline); } if (response.SessionCompleted) { await Kooboo.Mail.Transport.Incoming.Receive(session); session.ReSet(); } if (response.Close) { Dispose(); break; } // When enter the session state, read till the end . if (session.State == SmtpSession.CommandState.Data) { var externalto = AddressUtility.GetExternalRcpts(session); var counter = externalto.Count(); Kooboo.Data.Log.Instance.Email.Write("--recipants"); Kooboo.Data.Log.Instance.Email.WriteObj(externalto); Kooboo.Data.Log.Instance.Email.WriteObj(session.Log); if (counter > 0) { if (!Kooboo.Data.Infrastructure.InfraManager.Test(session.OrganizationId, Data.Infrastructure.InfraType.Email, counter)) { await WriteLineAsync("550 you have no enough credit to send emails"); Dispose(); break; } } var data = await _stream.ReadToDotLine(TimeSpan.FromSeconds(60)); var dataresponse = session.Data(data); if (dataresponse.SendResponse) { await WriteLineAsync(dataresponse.Render()); } if (dataresponse.SessionCompleted) { await Kooboo.Mail.Transport.Incoming.Receive(session); var tos = session.Log.Keys.Where(o => o.Name == SmtpCommandName.RCPTTO); string subject = "TO: "; if (tos != null) { foreach (var item in tos) { if (item != null && !string.IsNullOrWhiteSpace(item.Value)) { subject += item.Value; } } } if (counter > 0) { Kooboo.Data.Infrastructure.InfraManager.Add(session.OrganizationId, Data.Infrastructure.InfraType.Email, counter, subject); } session.ReSet(); OnDataCompleted(); } if (dataresponse.Close) { Dispose(); } } if (!cancellationToken.IsCancellationRequested) { commandline = await _reader.ReadLineAsync(); } } } catch (ObjectDisposedException) { // Caused by our active connection closing, no need to handle as exception } catch (Exception ex) { try { if (_client.Connected) { await WriteLineAsync("550 Internal Server Error"); } } catch { } Kooboo.Data.Log.Instance.Exception.Write(ex.Message + "\r\n" + ex.StackTrace + "\r\n" + ex.Source); } finally { _server._connectionManager.RemoveConnection(Id); Dispose(); } }