using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;

namespace ccc
{
    class SMTP 
    {
        Socket smtpSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        string strHost;
        string strPort;

        public static void Main() 
        {
            SMTP smtp = new SMTP("cc.kmit.edu.tw");
            smtp.SendMail("ccc@kmit.edu.tw", "ccckmit@gmail.com", "This is a mail send by C# SMTP1 program", "It's just a test mail !");
        }

        public SMTP(String pHost) {
            strHost = "cc.kmit.edu.tw";
            strPort = "25";
        }

        private void SendMail(string strFrom, string strTo, string strSubject, string strMsg)
        {
            string msg;

            try
            {
                // Connect to SMTP server
                debug("C: Trying to connect to host " + strHost + ", port: " + strPort);

                IPHostEntry IpHost = System.Net.Dns.GetHostEntry(strHost);
                IPAddress IPAdd = IpHost.AddressList[0];
                IPEndPoint IPEndAdd = new System.Net.IPEndPoint(IPAdd, Int32.Parse(strPort));

                // 嘗試與郵件伺服器建立連結
                smtpSocket.Connect(IPEndAdd);

                if (!smtpSocket.Connected)
                    debug("Unable to connect to " + strHost + ":" + strPort);

                // 郵件伺服器回傳 220 Ready 訊息
                if (!SMTPResponse("220"))
                    return;
            }
            catch (Exception ex)
            {
                debug("Socket: " + ex.ToString());
            }

            try
            {
                // Client端發出 HELO <Mail Server> 訊息以回應郵件伺服器
                msg = "HELO " + strHost + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 郵件伺服器回傳 250 OK 訊息
                if (!SMTPResponse("250"))
                {
                    return;
                }

                // Client端發出 MAIL FROM：<寄件者E-Mail Address> 訊息
                // 主要作用在於一旦有任何錯誤發生或郵件回應產生時
                // 會傳往此E-Mail Address
                msg = "MAIL FROM: " + strFrom + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 若寄件者 E-Mail Address 正確，郵件伺服器會回傳 250 OK 訊息
                // 否則會回傳 550 No such user 之訊息
                if (!SMTPResponse("250"))
                {
                    return;
                }

                string[] strArray = strTo.Split(",".ToCharArray());

                for (int i = 0; i < strArray.Length; i++)
                {
                    if (strArray[i].Trim().ToString() != "")
                    {
                        // Client端發出 RCPT TO：<收件者E-Mail Address> 指令
                        // 以代表收件者之E-Mail Address
                        msg = "RCPT TO: " + strArray[i].Trim().ToString() + "\r\n";

                        if (!SMTPSend(msg))
                        {
                            return;
                        }
                        // 若收件者E-Mail Address正確，郵件伺服器會回傳250 OK訊息
                        // 否則會回傳550 No such user之訊息
                        if (!SMTPResponse("250"))
                        {
                            return;
                        }
                    }
                }

                // 開始處理郵件標題及內容，Client端傳送 DATA 指令
                // 以告知郵件伺服器接著要開始傳送郵件標題及內容
                msg = "DATA" + "\r\n";

                if (!SMTPSend(msg))
                {
                    return;
                }
                // 若正確則郵件伺服器會回應354 Start mail input之訊息
                if (!SMTPResponse("354"))
                {
                    return;
                }

                // 傳送郵件標題 (Date) ，每一行須以<CR><LF>（換行歸位\r\n）結尾
                string strDate = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString();
                msg = "Date: " + strDate + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件標題 (From) 
                msg = "From: " + strFrom + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件標題 (To) 
                msg = "To: " + strTo + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件標題 (Subject) 
                msg = "Subject: " + strSubject + "\r\n" + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件內容
                msg = strMsg + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送歸位、換行、句點、歸位、換行字串，則<CR><LF>.<CR><LF>
                // 以代表郵件內容傳送結束
                msg = "\r\n" + "." + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 郵件伺服器會回傳250 OK訊息，代表成功傳送
                if (!SMTPResponse("250"))
                {
                    return;
                }

                // Client端發出 QUIT 指令，以要求結束通訊連結
                msg = "QUIT" + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 郵件伺服器回應 221 Service closing transmission channel 訊息
                // 以表示結束
                if (!SMTPResponse("221"))
                {
                    return;
                }

                smtpSocket.Shutdown(SocketShutdown.Both);
                smtpSocket.Close();
            }
            catch (Exception ex)
            {
                debug(ex.ToString());
            }
        }

        // 處理用戶端傳送訊息至郵件伺服器
        private bool SMTPSend(string strMsg)
        {
            byte[] byteMsg;

            try
            {
                debug("C: " + strMsg.ToString());

                byteMsg = Encoding.ASCII.GetBytes(strMsg.ToCharArray());
                smtpSocket.Send(byteMsg, byteMsg.Length, SocketFlags.None);

                return (true);
            }
            catch (Exception ex)
            {
                debug("SMTPSend Error: " + ex.ToString());

                smtpSocket.Shutdown(SocketShutdown.Both);
                smtpSocket.Close();

                return (false);
            }
        }

        // 處理郵件伺服器回傳訊息至用戶端
        private bool SMTPResponse(string strEcho)
        {
            byte[] RecvBytes = new byte[256];
            string strResponse = "";
            int bytes;

            try
            {
                bytes = smtpSocket.Receive(RecvBytes, RecvBytes.Length, 0);
                strResponse = Encoding.ASCII.GetString(RecvBytes, 0, bytes);

                debug("S: " + strResponse.ToString());

                if (!strResponse.StartsWith(strEcho))
                {
                    debug("SMTPResponse Error.");
                    smtpSocket.Shutdown(SocketShutdown.Both);
                    smtpSocket.Close();

                    return (false);
                }
                else
                {
                    return (true);
                }
            }
            catch (Exception ex)
            {
                debug("SMTPResponse Error: " + ex.ToString());

                smtpSocket.Shutdown(SocketShutdown.Both);
                smtpSocket.Close();

                return (false);
            }
        }

        public static void debug(String msg) { Console.WriteLine(msg); }
    }
}

/*
    private void ProcessMail(string strHost, string strPort, string strFrom, string strTo, string strSubject, string strMsg)
        {
            string msg;

            try
            {
                // Connect to SMTP server
                debug("C: Trying to connect to host " + strHost + ", port: " + strPort);
                
                IPHostEntry IpHost = System.Net.Dns.GetHostEntry(strHost);
                IPAddress IPAdd = IpHost.AddressList[0];
                IPEndPoint IPEndAdd = new System.Net.IPEndPoint(IPAdd, Int32.Parse(strPort));

                // 嘗試與郵件伺服器建立連結
                smtpSocket.Connect(IPEndAdd);

                if (!smtpSocket.Connected)
                    debug("Unable to connect to " + strHost + ":" + strPort);

                // 郵件伺服器回傳 220 Ready 訊息
                if (!SMTPResponse("220"))
                    return;
            }
            catch (Exception ex)
            {
                debug("Socket: " + ex.ToString());
            }

            try
            {
                // Client端發出 HELO <Mail Server> 訊息以回應郵件伺服器
                msg = "HELO " + strHost + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 郵件伺服器回傳 250 OK 訊息
                if (!SMTPResponse("250"))
                {
                    return;
                }

                // Client端發出 MAIL FROM：<寄件者E-Mail Address> 訊息
                // 主要作用在於一旦有任何錯誤發生或郵件回應產生時
                // 會傳往此E-Mail Address
                msg = "MAIL FROM: " + strFrom + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 若寄件者 E-Mail Address 正確，郵件伺服器會回傳 250 OK 訊息
                // 否則會回傳 550 No such user 之訊息
                if (!SMTPResponse("250"))
                {
                    return;
                }

                string[] strArray = strTo.Split(",".ToCharArray());

                for (int i = 0; i < strArray.Length; i++)
                {
                    if (strArray[i].Trim().ToString() != "")
                    {
                        // Client端發出 RCPT TO：<收件者E-Mail Address> 指令
                        // 以代表收件者之E-Mail Address
                        msg = "RCPT TO: " + strArray[i].Trim().ToString() + "\r\n";

                        if (!SMTPSend(msg))
                        {
                            return;
                        }
                        // 若收件者E-Mail Address正確，郵件伺服器會回傳250 OK訊息
                        // 否則會回傳550 No such user之訊息
                        if (!SMTPResponse("250"))
                        {
                            return;
                        }
                    }
                }

                // 開始處理郵件標題及內容，Client端傳送 DATA 指令
                // 以告知郵件伺服器接著要開始傳送郵件標題及內容
                msg = "DATA" + "\r\n";

                if (!SMTPSend(msg))
                {
                    return;
                }
                // 若正確則郵件伺服器會回應354 Start mail input之訊息
                if (!SMTPResponse("354"))
                {
                    return;
                }

                // 傳送郵件標題 (Date) ，每一行須以<CR><LF>（換行歸位\r\n）結尾
                string strDate = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString();
                msg = "Date: " + strDate + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件標題 (From) 
                msg = "From: " + strFrom + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件標題 (To) 
                msg = "To: " + strTo + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件標題 (Subject) 
                msg = "Subject: " + strSubject + "\r\n" + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送郵件內容
                msg = strMsg + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }

                // 傳送歸位、換行、句點、歸位、換行字串，則<CR><LF>.<CR><LF>
                // 以代表郵件內容傳送結束
                msg = "\r\n" + "." + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 郵件伺服器會回傳250 OK訊息，代表成功傳送
                if (!SMTPResponse("250"))
                {
                    return;
                }

                // Client端發出 QUIT 指令，以要求結束通訊連結
                msg = "QUIT" + "\r\n";
                if (!SMTPSend(msg))
                {
                    return;
                }
                // 郵件伺服器回應 221 Service closing transmission channel 訊息
                // 以表示結束
                if (!SMTPResponse("221"))
                {
                    return;
                }

                smtpSocket.Shutdown(SocketShutdown.Both);
                smtpSocket.Close();
            }
            catch (Exception ex)
            {
                debug(ex.ToString());
            }
        }

        // 處理用戶端傳送訊息至郵件伺服器
        private bool SMTPSend(string strMsg)
        {
            byte[] byteMsg;

            try
            {
                debug("C: " + strMsg.ToString());

                byteMsg = Encoding.ASCII.GetBytes(strMsg.ToCharArray());
                smtpSocket.Send(byteMsg, byteMsg.Length, SocketFlags.None);

                return (true);
            }
            catch (Exception ex)
            {
                debug("SMTPSend Error: " + ex.ToString());

                smtpSocket.Shutdown(SocketShutdown.Both);
                smtpSocket.Close();

                return (false);
            }
        }

*/
