Search code examples
emailsmtpsmtpclientmailkit

MailKit SMTP client fails with "Unable to parse status code returned by the server" no matter what I do


I am trying to debug the messages sent by the MailKit SMTP module in the product I support. So I put together a quick C program that is probably the worst SMTP implementation ever (I'm not an experienced programmer) to help me parse the messages my application is generating. The application listens on port 25 and does the basic SMTP (noauth, no SSL) handshake, so I get to the point where MailKit would dump the message so I can see how it is formatted.

When MailKit connects, I send back a string "220 test.com SMTP Server", then the following happens:

  1. MailKit replies with "EHLO hostname.domain.com".
  2. My application sends back "250 hostname.domain.com".
  3. MailKit sends to my application "MAIL FROM:[email protected]"

From here, MailKit always crashes with "Unable to parse status code returned by the server" I've tried all sorts of answers from all the SMTP tutorials I could find. In a moment of desperation, I configured my production mail server to accept unauthenticated relay for my subnet and did a pcap. I tried to implement in C the exact same string I got from the pcap from postfix (in postfix, the email goes out fine):

char *response = "250-server.test.com\n250-SIZE 104857600\n250-STARTTLS\n250-ENHANCEDSTATUSCODE\n250-8BITMIME\n250-DNS\n250-CHUNKING\r\n";

In this case, MailKit never sends me MAIL FROM... it just sits there waiting for a very long time for a response before timing out.

My question here is... I couldn't find in the MailKit documentation (and the source code didn't help me much)... What is the correct format of answer that MailKit will accept so it proceeds with sending RCPT TO and the body of the message?

The error comes from MailKit.Net.Smtp.SmtpStream.ReadResponse.


Solution

  • Change this:

    char *response = "250-server.test.com\n250-SIZE 104857600\n250-STARTTLS\n250-ENHANCEDSTATUSCODE\n250-8BITMIME\n250-DNS\n250-CHUNKING\r\n";
    

    to this:

    char *response = "250-server.test.com\n250-SIZE 104857600\n250-STARTTLS\n250-ENHANCEDSTATUSCODE\n250-8BITMIME\n250-DNS\n250 CHUNKING\r\n";
    

    The - character after the SMTP status code tells the client that there is at least 1 more line of the response, but in your code, the last line of the response has the - which is why MailKit's SmtpClient continues to wait for more data.

    Update:

    If all you want to do is check the MIME formatting that MimeKit/MailKit is doing, do this instead of trying to write your own mail server:

    var options = FormatOptions.Default.Clone();
    options.NewLineFormat = NewLineFormat.Dos;
    
    message.Prepare(EncodingConstraint.EightBit);
    message.WriteTo(options, "fileName.txt");