Exemplo n.º 1
0
        public override async Task ExecuteAsync(CancellationToken token)
        {
            if (string.IsNullOrEmpty(_builder.PendingMail?.FromPath?.Mailbox) ||
                _builder.PendingMail?.Recipents?.Count == 0 ||
                _builder.PendingMail?.IsBinary != true)
            {
                await _session.SendReplyAsync(SmtpReplyCode.BadSequence, "Bad sequence", token);

                return;
            }

            string[] parts = Arguments?.Split(' ');
            if (parts == null || parts.Length == 0 || parts.Length > 2)
            {
                await _session.SendReplyAsync(SmtpReplyCode.InvalidArguments, "Length required, optional LAST", token);

                return;
            }

            if (!int.TryParse(parts[0], out int length) || length < 1)
            {
                await _session.SendReplyAsync(SmtpReplyCode.InvalidArguments, "Length must be positive integer", token);

                return;
            }

            var last = false;

            if (parts.Length == 2)
            {
                if (!string.Equals("LAST", parts[1], StringComparison.OrdinalIgnoreCase))
                {
                    await _session.SendReplyAsync(SmtpReplyCode.InvalidArguments, "LAST expected", token);

                    return;
                }

                last = true;
            }

            using (IMailWriteReference mailReference = await _mailQueue.NewMailAsync(
                       _builder.PendingMail.FromPath.Mailbox,
                       _builder.PendingMail.Recipents.ToImmutableList(),
                       token))
            {
                using (Stream mailStream = mailReference.BodyStream)
                {
                    var chunk     = new byte[1000];
                    var totalRead = 0;
                    do
                    {
                        int toRead = Math.Min(chunk.Length, length - totalRead);
                        int read   = await _connection.ReadBytesAsync(chunk, 0, toRead, token);

                        totalRead += read;
                        await mailStream.WriteAsync(chunk, 0, read, token);
                    } while (totalRead < length);
                }

                await _mailQueue.SaveAsync(mailReference, token);
            }

            await _session.SendReplyAsync(SmtpReplyCode.Okay, $"Recieved {length} octets", token);

            if (last)
            {
                _builder.PendingMail = null;
                await _session.SendReplyAsync(SmtpReplyCode.Okay, "Message complete", token);
            }
        }
Exemplo n.º 2
0
        public override async Task ExecuteAsync(CancellationToken token)
        {
            if (string.IsNullOrEmpty(_builder.PendingMail?.FromPath?.Mailbox) ||
                _builder.PendingMail?.Recipents?.Count == 0 ||
                _builder.PendingMail?.IsBinary == true)
            {
                await _channel.SendReplyAsync(SmtpReplyCode.BadSequence, "Bad sequence", token);

                return;
            }

            await _channel.SendReplyAsync(SmtpReplyCode.StartMail, "Send data, end with .<CR><LF>", token);

            var rejected = false;

            using (IMailWriteReference reference = await _mailQueue.NewMailAsync(
                       _builder.PendingMail.FromPath.Mailbox,
                       _builder.PendingMail.Recipents.ToImmutableList(),
                       token))
            {
                using (var mailWriter = new StreamWriter(reference.BodyStream, new UTF8Encoding(false)))
                {
                    await mailWriter.WriteLineAsync(
                        $"Received: FROM {_channel.ConnectedHost} ({_connectionInformation.RemoteAddress}) BY {_settings.DomainName} ({_connectionInformation.LocalAddress}); {DateTime.UtcNow:ddd, dd MMM yyy HH:mm:ss zzzz}");

                    string line;
                    while ((line = await _reader.ReadLineAsync(Encoding.UTF8, token)) != ".")
                    {
                        if (!rejected &&
                            !_channel.IsAuthenticated &&
                            _settings.UnauthenticatedMessageSizeLimit != 0 &&
                            _settings.UnauthenticatedMessageSizeLimit <= mailWriter.BaseStream.Length)
                        {
                            await _channel.SendReplyAsync(SmtpReplyCode.ExceededQuota, "Message rejected, too large", token);

                            mailWriter.Dispose();
                            reference.Dispose();
                            rejected = true;
                        }

                        if (rejected)
                        {
                            continue;
                        }

                        await mailWriter.WriteLineAsync(line);

                        await mailWriter.FlushAsync();
                    }
                }

                if (!rejected)
                {
                    await _mailQueue.SaveAsync(reference, token);
                }
            }

            _builder.PendingMail = null;
            if (!rejected)
            {
                await _channel.SendReplyAsync(SmtpReplyCode.Okay, "OK", token);
            }
        }