예제 #1
0
        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();
            }
        }