Exemplo n.º 1
0
        /// <summary>
        /// Send the data to the server
        /// </summary>
        /// <param name="data">Data to send to the server</param>
        /// <param name="failedCallback">Action to call if fails to send.</param>
        private async Task <MantaOutboundClientSendResult> ExecDataAsync(string data)
        {
            await SmtpStream.WriteLineAsync("DATA");

            string response = await SmtpStream.ReadAllLinesAsync(); // Data response or Mail From if pipelining

            // If the remote MX supports pipelining then we need to check the MAIL FROM and RCPT to responses.
            if (_CanPipeline)
            {
                // Check MAIL FROM OK.
                if (!response.StartsWith("250"))
                {
                    await SmtpStream.ReadAllLinesAsync(); // RCPT TO

                    await SmtpStream.ReadAllLinesAsync(); // DATA

                    return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord));
                }


                // Check RCPT TO OK.
                response = await SmtpStream.ReadAllLinesAsync();

                if (!response.StartsWith("250"))
                {
                    await SmtpStream.ReadAllLinesAsync(); // DATA

                    return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord));
                }

                // Get the Data Command response.
                response = await SmtpStream.ReadAllLinesAsync();
            }

            if (!response.StartsWith("354"))
            {
                return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord));
            }

            // Send the message data using the correct transport MIME
            SmtpStream.SetSmtpTransportMIME(_DataTransportMime);
            await SmtpStream.WriteAsync(data, false);

            await SmtpStream.WriteAsync(MtaParameters.NewLine + "." + MtaParameters.NewLine, false);

            // Data done so return to 7-Bit mode.
            SmtpStream.SetSmtpTransportMIME(SmtpTransportMIME._7BitASCII);

            response = await SmtpStream.ReadAllLinesAsync();

            if (!response.StartsWith("250"))
            {
                return(new MantaOutboundClientSendResult(MantaOutboundClientResult.RejectedByRemoteServer, response, _VirtualMta, _MXRecord));
            }

            _MessagesAccepted++;
            return(new MantaOutboundClientSendResult(MantaOutboundClientResult.Success, response, _VirtualMta, _MXRecord));
        }
Exemplo n.º 2
0
        public async Task TestWriteAsync()
        {
            using (var stream = new SmtpStream(new DummyNetworkStream(), new NullProtocolLogger())) {
                var     memory = (MemoryStream)stream.Stream;
                var     buffer = new byte[8192];
                var     buf1k  = new byte[1024];
                var     buf4k  = new byte[4096];
                var     buf9k  = new byte[9216];
                byte [] mem;

                using (var rng = new RNGCryptoServiceProvider()) {
                    rng.GetBytes(buf1k);
                    rng.GetBytes(buf4k);
                    rng.GetBytes(buf9k);
                }

                // Test #1: write less than 4K to make sure that SmtpStream buffers it
                await stream.WriteAsync(buf1k, 0, buf1k.Length);

                Assert.AreEqual(0, memory.Length, "#1");

                // Test #2: make sure that flushing the SmtpStream flushes the entire buffer out to the network
                await stream.FlushAsync();

                Assert.AreEqual(buf1k.Length, memory.Length, "#2");
                mem = memory.GetBuffer();
                for (int i = 0; i < buf1k.Length; i++)
                {
                    Assert.AreEqual(buf1k[i], mem[i], "#2 byte[{0}]", i);
                }
                memory.SetLength(0);

                // Test #3: write exactly 4K to make sure it passes through w/o the need to flush
                await stream.WriteAsync(buf4k, 0, buf4k.Length);

                Assert.AreEqual(buf4k.Length, memory.Length, "#3");
                mem = memory.GetBuffer();
                for (int i = 0; i < buf4k.Length; i++)
                {
                    Assert.AreEqual(buf4k[i], mem[i], "#3 byte[{0}]", i);
                }
                memory.SetLength(0);

                // Test #4: write 1k and then write 4k, make sure that only 4k passes thru (last 1k gets buffered)
                await stream.WriteAsync(buf1k, 0, buf1k.Length);

                await stream.WriteAsync(buf4k, 0, buf4k.Length);

                Assert.AreEqual(4096, memory.Length, "#4");
                await stream.FlushAsync();

                Assert.AreEqual(buf1k.Length + buf4k.Length, memory.Length, "#4");
                Array.Copy(buf1k, 0, buffer, 0, buf1k.Length);
                Array.Copy(buf4k, 0, buffer, buf1k.Length, buf4k.Length);
                mem = memory.GetBuffer();
                for (int i = 0; i < buf1k.Length + buf4k.Length; i++)
                {
                    Assert.AreEqual(buffer[i], mem[i], "#4 byte[{0}]", i);
                }
                memory.SetLength(0);

                // Test #5: write 9k and make sure only the first 8k goes thru (last 1k gets buffered)
                await stream.WriteAsync(buf9k, 0, buf9k.Length);

                Assert.AreEqual(8192, memory.Length, "#5");
                await stream.FlushAsync();

                Assert.AreEqual(buf9k.Length, memory.Length, "#5");
                mem = memory.GetBuffer();
                for (int i = 0; i < buf9k.Length; i++)
                {
                    Assert.AreEqual(buf9k[i], mem[i], "#5 byte[{0}]", i);
                }
                memory.SetLength(0);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Send the data to the server
        /// </summary>
        /// <param name="data">Data to send to the server</param>
        /// <param name="failedCallback">Action to call if fails to send.</param>
        public async Task <bool> ExecDataAsync(string data, Action <string> failedCallback, Func <string, Task> successCallbackAsync)
        {
            if (!base.Connected)
            {
                return(false);
            }

            _LastActive = DateTime.UtcNow;
            IsActive    = true;

            await SmtpStream.WriteLineAsync("DATA");

            string response = await SmtpStream.ReadAllLinesAsync();

            // If the remote MX supports pipelining then we need to check the MAIL FROM and RCPT to responses.
            if (_CanPipeline)
            {
                // Check MAIL FROM OK.
                if (!response.StartsWith("250"))
                {
                    failedCallback(response);
                    IsActive = false;
                    return(false);
                }


                // Check RCPT TO OK.
                response = await SmtpStream.ReadAllLinesAsync();

                if (!response.StartsWith("250"))
                {
                    failedCallback(response);
                    IsActive = false;
                    return(false);
                }

                // Get the Data Command response.
                response = await SmtpStream.ReadAllLinesAsync();
            }

            _LastActive = DateTime.UtcNow;

            if (!response.StartsWith("354"))
            {
                failedCallback(response);
                IsActive = false;
                return(false);
            }

            // Increment the data commands as server has responded positiely.
            _DataCommands++;

            // Send the message data using the correct transport MIME
            SmtpStream.SetSmtpTransportMIME(_DataTransportMime);
            await SmtpStream.WriteAsync(data, false);

            await SmtpStream.WriteAsync(MtaParameters.NewLine + "." + MtaParameters.NewLine, false);

            _LastActive = DateTime.UtcNow;

            // Data done so return to 7-Bit mode.
            SmtpStream.SetSmtpTransportMIME(SmtpTransportMIME._7BitASCII);


            response = await SmtpStream.ReadAllLinesAsync();

            _LastActive = DateTime.UtcNow;
            IsActive    = false;


            if (!response.StartsWith("250"))
            {
                failedCallback(response);
            }
            else
            {
                await successCallbackAsync(response);
            }


            // If max messages have been sent quit the connection.
            if (_DataCommands >= OutboundRuleManager.GetMaxMessagesPerConnection(MXRecord, MtaIpAddress))
            {
                ExecQuitAsync().Wait();
            }

            return(true);
        }