1

I'm trying to solve strange problem that's causing the SMTP server I normally use to return a "unknown recipient" message for my own email address. In production I use a different SMTP server so this just blocks my testing.

I tried to use Fiddler to analyse the traffic but apparently Fiddler doesn't detect any SMTP traffic. I'm untrained with WireShark and this is just a small side project I can't spend large amount of time on so I thought I'd just piece together a small TCP service instead just to see what's being sent by the SmtpClient instance I use.

This is the TcpListener code ...

class Service
{
    public Task Listen(int port, CancellationToken ct, TcpHandler tcpHandler = null)
    {
        tcpHandler = tcpHandler ?? defaultTcpHandler;
        return Task.Run(async () => 
        {
            var endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
            var listener = new TcpListener(endpoint);
            listener.Start();
            try
            {
                while (!ct.IsCancellationRequested)
                {
                    var client = await listener.AcceptTcpClientAsync();
                    handleRequestAsync(client, tcpHandler, ct);
                }
                listener.Stop();
            }
            catch (SocketException ex)
            {
                Console.WriteLine($"SocketException: {ex}");
            }
            finally
            {
                listener.Stop();
            }
        }, 
        ct);
    }

    void handleRequestAsync(TcpClient client, TcpHandler tcpHandler, CancellationToken ct)
    {
        Task.Run(async () => 
        {
            var stream = client.GetStream();
            if (!stream.CanRead)
                return;

            var sb = new StringBuilder();
            var buffer = new byte[4096];
            int receivedCount;
            while ((receivedCount = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
            {
                var received = Encoding.ASCII.GetString(buffer, 0, receivedCount);
                sb.Append(received);
            }
            var request = sb.ToString();
            if (request.Length != 0 && tcpHandler(sb.ToString(), out var response))
            {
                var send = Encoding.ASCII.GetBytes(response);
                stream.Write(send, 0, send.Length);
                stream.Flush();
            }
            client.Close();
        });
    }

Yes, the code is pretty naive with no real error handling etc. but, again, this was just a way to see what's being sent. The problem is that the call to stream.ReadAsync blocks and never returns. I also checked the TcpClient.Available property and it returns zero (0). Eventually the SmtpClient times out and nothing ever seems to get sent. I also haven't deep-dived into the SMTP protocol so maybe I'm missing something? Do I need to somehow acknowledge the connection before data gets sent by SmtpClient?

I haven't been doing much network coding for alot of years and I was never a ninja in this field. Any pointers or hints would be greatly appreciated.

Cheers!

noseratio
  • 59,932
  • 34
  • 208
  • 486
Jonas Rembratt
  • 1,550
  • 3
  • 17
  • 39
  • Hard to come up with a definitive answer without being able to repro, but were and how do you call your `Listen` method? Also, you shouldn't be doing a fire-and-forget `Task.Run` inside `handleRequestAsync`, you should keep a track of it. See if [this](https://stackoverflow.com/a/21018042/1768303) helps anyhow. – noseratio Aug 07 '18 at 09:44
  • I call the `Listen` method from the `Main` method (it's a console app) and then just enter an infinite loop. Like I said, this is naive code and not meant to be an actual SMTP server at all. I just wanted a way to diagnose what is being sent from the `SmtpClient`. As it stands, nothing seems to be sent at all, which cannot be true, seeing that I get a server error when it comunicates with the actual (test) SMTP server. – Jonas Rembratt Aug 07 '18 at 18:39

0 Answers0