Sending an Email in C# When Server Uses GREET_PAUSE
I wrote a process for a client which would send an email through their email server when a process completed. Their server did not require any kind of authentication or SSL, so the code to do this was very simple:
1 2 3 4 5 6 7 8 9 10 | public static void SendEmail(string to, string from, string subject, string message, string host, int port) { SmtpClient c = new SmtpClient(host, port); MailMessage m = new MailMessage(from, to, subject, message); m.IsBodyHtml = true; c.Send(m); } |
Simple, eh? But it would fail. If I telnet’ed into their server and typed the SMTP commands to send an email, I would get a 550 5.0.0 Command Rejected” error message at the point where I try to send a “RCPT TO:” SMTP command. What’s the deal?!
Well, apparently the server did have a restriction that I had so far not known about. It had been configured with a GREET_PAUSE value for all emails. Typically that setting should only be set for incoming emails from external servers, and not for internal emails like this. But it was set for all emails.
GREET_PAUSE means that once an SMTP connection is made, the client who is connecting must WAIT until the server recognizes their connection before “blasting” SMTP commands through. Apparently SMTPClient just blasts the commands through. If a SINGLE character is received in that timespan, the server will reply as normal, but will reject any and all emails that are sent through.
I tried a couple fancy ways to make SMTPClient wait for a few seconds before sending data, but could not find an easy way. Apparently it does not support this capability out of the box (such that I could find.) So I resolved to just writing the email code myself. It’s not hard to do.
I added a greet_delay_ms integer to my parameters on my function:
1 2 | public static void SendEmail(string to, string from, string subject, string message, string host, int port, int greet_delay_ms) |
And replaced the simple SMTPClient code with this more complex code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public static void SendEmail(string to, string from, string subject, string message, string host, int port, int greet_delay_ms) { TcpClient c = new TcpClient(host, port); StreamWriter sw = new StreamWriter(c.GetStream()); StreamReader sr = new StreamReader(c.GetStream()); string data = ""; // Wait the specified amount of time before sending an email // could probably also just do a sr.ReadLine() and let it block System.Threading.Thread.Sleep(greet_delay_ms); sw.WriteLine("helo " + from.Substring(from.IndexOf("@") + 1)); sw.Flush(); data = sr.ReadLine(); sw.WriteLine("MAIL FROM:" + from); sw.Flush(); data = sr.ReadLine(); sw.WriteLine("RCPT TO:" + to); sw.Flush(); data = sr.ReadLine(); sw.WriteLine("DATA"); sw.Flush(); data = sr.ReadLine(); sw.WriteLine("Subject: " + subject); sw.Flush(); sw.WriteLine(message); sw.Flush(); sw.WriteLine("."); sw.Flush(); data = sr.ReadLine(); c.Client.Close(); c.Close(); } |
Once I passed in 8000 or so as the time to wait, the emails poured through just fine. 8 seconds is a while to wait, but apparently that’s what this server requires.
Follow Dave on Twitter