Click here to Skip to main content
15,881,898 members
Articles / Programming Languages / C#
Article

Mail library using sockets, in C#

Rate me:
Please Sign up or sign in to vote.
3.06/5 (16 votes)
27 May 2004 78.5K   1.1K   29   15
My own mail library without CDO and System.Web.Mail.

1. Introduction

This mail library is an extension of SocketHelper which is described in my previous article.

No CDO needed and no System.Web.Mail which is a package to CDO needed.

Now, let's see what is inside.

2. Classes

  1. MailMessage
  2. SmtpServer

MailMessage is used for storing mail messages (currently doesn't support attachments).

SmtpServer is a class to communicate with SMTP servers, inside which there is a SocketHelper (with some updates, download source code for detail).

3. Code Detail

The class MailMessage:

C#
public class MailMessage
{
    public enum BodyFormat
    {
        HTML,TEXT
    }

    private string sFrom;
    private string sTo;
    private string sCc;
    private string sSubject;
    private BodyFormat bfFormat=BodyFormat.TEXT;
    private string sBody;
    private string sFromName;
    private string sToName;

    public string Cc
    {
        get
        {
            return sCc;
        }
        set
        {
            sCc=value;
        }
    }

    public string FromName
    {
        get
        {
            if(sFromName==null || sFromName=="")
                sFromName=sFrom;

            return sFromName;
        }
        set
        {
            sFromName=value;
        }
    }

    public string ToName
    {
        get
        {
            if(sToName==null || sToName=="")
                sToName=sTo;

            return sToName;
        }
        set
        {
            sToName=value;
        }
    }

    public string From
    {
        get
        {
            return sFrom;
        }
        set
        {
            sFrom=value;
        }
    }

    public string To
    {
        get
        {
            return sTo;
        }
        set
        {
            sTo=value;
        }
    }

    public string Subject
    {
        get
        {
            return sSubject;
        }
        set
        {
            sSubject=value;
        }
    }

    public string Body
    {
        get
        {
            return sBody;
        }
        set
        {
            sBody=value;
        }
    }

    public BodyFormat MailFormat
    {
        get
        {
            return bfFormat;
        }
        set
        {
            bfFormat=value;
        }
    }

    public MailMessage()
    {
        //
        // TODO: Add constructor logic here
        //
    }

    public override string ToString()
    {
        StringBuilder sb=new StringBuilder();
        sb.AppendFormat("From: {0}\r\n",this.FromName);
        sb.AppendFormat("To: {0}\r\n",this.ToName);
        if(this.Cc!=null && this.Cc!="")
        {
            sb.AppendFormat("Cc: {0}\r\n",this.Cc.Replace(";",","));
        }
        sb.AppendFormat("Date: {0}\r\n",
          DateTime.Now.ToString("ddd, d M y H:m:s z"));
        sb.AppendFormat("Subject: {0}\r\n",this.Subject);
        sb.AppendFormat("X-Mailer: vmlinux.Net.Mail.SmtpServer\r\n");
        switch(this.MailFormat)
        {
            case BodyFormat.TEXT:
              sb.AppendFormat("Content-type:text/plain;Charset=GB2312\r\n");
              break;
            case BodyFormat.HTML:
              sb.AppendFormat("Content-type:text/html;Charset=GB2312\r\n");
              break;
            default:
              break;
        }
        sb.AppendFormat("\r\n{0}\r\n",this.Body);
        return sb.ToString();
    }
}

I get all the message inside mail through the method ToString().

Now, the following is class SmtpServer:

C#
    public class SmtpServer
    {
        private string sServer;
        private int iPort;
        private bool bAuth=false;
        private string sUser;
        private string sPass;
        private StringBuilder sbLog=null;
        private bool bLog=true;
        private SocketHelper helper=null;
        private TalkState state=TalkState.WaitInit;

        public enum TalkState
        {
            WaitInit,Initialized,SignedIn,LoginFailed,Ended
        }

        protected SocketHelper Helper
        {
            get
            {
                if(helper==null)
                    helper=new SocketHelper(this.Server,this.Port);

                return helper;
            }
        }

        public bool LogEvent
        {
            get
            {
                return bLog;
            }
            set
            {
                bLog=value;
            }
        }

        public string LogMessage
        {
            get
            {
                if(this.LogEvent)
                    return sbLog.ToString();
                else
                    return "";
            }
        }

        public string Server
        {
            get
            {
                return sServer;
            }
            set
            {
                sServer=value;
            }
        }

        public int Port
        {
            get
            {
                return iPort;
            }
            set
            {
                iPort=value;
            }
        }

        public bool RequireAuthorization
        {
            get
            {
                return bAuth;
            }
            set
            {
                bAuth=value;
            }
        }

        public string AuthUser
        {
            get
            {
                return sUser;
            }
            set
            {
                sUser=value;
            }
        }

        public string AuthPass
        {
            get
            {
                return sPass;
            }
            set
            {
                sPass=value;
            }
        }

        public SmtpServer()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public void Init()
        {
            Log(helper.GetFullResponse());
            Helper.SendCommand("EHLO "+this.Server);
            Log(Helper.GetFullResponse());
            state=TalkState.Initialized;
        }

        public bool Login()
        {
            if(this.RequireAuthorization)
            {
                Helper.SendCommand("AUTH LOGIN");
                Log(Helper.GetFullResponse());
                Helper.SendCommand(
                    Convert.ToBase64String(
                    Encoding.Default.GetBytes(this.AuthUser)));
                Log(Helper.GetFullResponse());
                Helper.SendCommand(
                    Convert.ToBase64String(
                    Encoding.Default.GetBytes(this.AuthPass)));
                Log(Helper.GetFullResponse());

                if(Helper.GetResponseState()==235)
                {
                    state=TalkState.SignedIn;
                    return true;
                }
                else
                {
                    state=TalkState.LoginFailed;
                    return false;
                }
//                return (Helper.GetResponseState()==235);
            }
            else
            {
                state=TalkState.SignedIn;
                return true;
            }
        }

        public void SendKeep(MailMessage msg)
        {
            if((state==TalkState.Initialized && 
               !this.RequireAuthorization) || state==TalkState.SignedIn)
            {
                Helper.SendCommand("MAIL From:"+msg.From);
                Log(Helper.GetFullResponse());
                Helper.SendCommand("RCPT To:"+msg.To);
                Log(Helper.GetFullResponse());
                Helper.SendCommand("DATA");
                Log(Helper.GetFullResponse());
                Helper.SendData(Encoding.Default.GetBytes(msg.ToString()));
                Helper.SendCommand(".");
                Log(Helper.GetFullResponse());
            }
        }

        public void Quit()
        {
            Helper.SendCommand("QUIT");
            Helper.Close();
            state=TalkState.Ended;
        }

        public bool Send(MailMessage msg)
        {
            if(state==TalkState.Ended)
                return false;

            Log(Helper.GetFullResponse());
            Helper.SendCommand("EHLO "+this.Server);
            Log(Helper.GetFullResponse());
            if(this.RequireAuthorization)
            {
                Helper.SendCommand("AUTH LOGIN");
                Log(Helper.GetFullResponse());
                Helper.SendCommand(
                    Convert.ToBase64String(
                    Encoding.Default.GetBytes(this.AuthUser)));
                Log(Helper.GetFullResponse());
                Helper.SendCommand(
                    Convert.ToBase64String(
                    Encoding.Default.GetBytes(this.AuthPass)));
                Log(Helper.GetFullResponse());
                if(Helper.GetResponseState()!=235)
                {
                    Helper.SendCommand("QUIT");
                    Helper.Close();
                    state=TalkState.Ended;
                    return false;
                }
            }
            Helper.SendCommand("MAIL From:"+msg.From);
            Log(Helper.GetFullResponse());
            Helper.SendCommand("RCPT To:"+msg.To);
            Log(Helper.GetFullResponse());
            Helper.SendCommand("DATA");
            Log(Helper.GetFullResponse());
            Helper.SendData(Encoding.Default.GetBytes(msg.ToString()));
            Helper.SendCommand(".");
            Log(Helper.GetFullResponse());
            Helper.SendCommand("QUIT");
            Helper.Close();
            state=TalkState.Ended;
            return true;
        }

        private void Log(string msg)
        {
            if(this.LogEvent)
            {
                if(sbLog==null)
                    sbLog=new StringBuilder();

                sbLog.AppendFormat("{0}\r\n",msg);
            }
        }
    }

You can send multiple emails in one connection or simply send one.

To send multiple emails, follow this command sequence:

  1. Init --- to receive server response and say hello.
  2. Login --- if the server requires user login.
  3. SendKeep --- send mail and keep connection.
  4. ... --- more mail through SendKeep.
  5. Quit --- say good bye to server.

If you are sending only one mail in one connection, simply call Send.

So that's it.

4. TODO

  1. error handling
  2. attachments

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionworks without SMTP server ? Pin
Member 353722922-Sep-09 0:47
Member 353722922-Sep-09 0:47 
General[Message Deleted] Pin
it.ragester2-Apr-09 21:50
it.ragester2-Apr-09 21:50 
GeneralSend Email Pin
am2h25-May-08 22:36
am2h25-May-08 22:36 
GeneralSMTP Pin
programet_nje15-Apr-08 6:52
programet_nje15-Apr-08 6:52 
GeneralCompact Framework Pin
chmod222224-Jul-07 7:02
chmod222224-Jul-07 7:02 
Great,
Rewrote it just a bit at
sb.AppendFormat("To: {0}\r\n",this.ToName); //not supported

put it to

sb.Append(string.Format("To: {0}\r\n", this.ToName));

and it works on my pocket pc.

Thank you Wink | ;)
GeneralSending Progress Pin
Kostas Dak4-Sep-06 21:24
Kostas Dak4-Sep-06 21:24 
GeneralTrouble Pin
_BlackLine_21-May-06 2:00
_BlackLine_21-May-06 2:00 
GeneralRe: Trouble Pin
_BlackLine_21-May-06 2:27
_BlackLine_21-May-06 2:27 
GeneralVery nice! Pin
_BlackLine_21-May-06 1:42
_BlackLine_21-May-06 1:42 
GeneralWierd dates on sent messages Pin
ScottEllisNovatex21-Apr-05 19:52
ScottEllisNovatex21-Apr-05 19:52 
GeneralRe: Wierd dates on sent messages Pin
jaygeek14-Sep-05 8:19
jaygeek14-Sep-05 8:19 
GeneralYeah... Nice... Pin
HumanOsc27-May-04 21:58
HumanOsc27-May-04 21:58 
GeneralRe: Yeah... Nice... Pin
Giles27-May-04 22:46
Giles27-May-04 22:46 
GeneralRe: Yeah... Nice... Pin
vmlinuxx27-May-04 22:59
vmlinuxx27-May-04 22:59 
GeneralRe: Yeah... Nice... Pin
HumanOsc28-May-04 21:40
HumanOsc28-May-04 21:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.