SMTP mail send class written in C #

Source: Internet
Author: User
Tags foreach auth base64 bool count error code getstream hash
Using System;
Using System.IO;
Using System.Text;
Using System.Net;
Using System.Net.Sockets;
Using System.Collections;
Using System.Collections.Specialized; Using KSN.
exceptions; Using KSN.
Validate; Namespace KSN. 
  Web.mail {///<summary>///mail content///</summary> public class MailMessage {private string sender=null;
  Private StringCollection receivers=new stringcollection ();
  private string subject= "";
  private string Xmailer= "";
  Private StringCollection attachments=new stringcollection ();
  Private Mailencodings mailencoding=mailencodings.gb2312;
  Private Mailtypes mailtype=mailtypes.html;
  Private byte[] mailbody=null;
   <summary>///Gets or sets the sender///</summary> public string Sender {Get{return this.sender;}
  Set{this.sender=value;} ///<summary>///Gets the recipient address collection///</summary> public stringcollection receivers {Get{return this.
  Receivers;}
 ///<summary>///Gets or sets the message subject///</summary> public string Subject {Get{return this.subject;}
  Set{this.subject=value;}
   ///<summary>///Gets or sets the mail transporter///</summary> public string Xmailer {Get{return This.xmailer;}
  Set{this.xmailer=value;} ///<summary>///Get attachment list///</summary> public stringcollection Attachments {Get{return THIS.A
  Ttachments;} ///<summary>///Gets or sets how the message is encoded///</summary> public mailencodings mailencoding {get{return th
   is.mailencoding;}
  Set{this.mailencoding=value;} ///<summary>///Get or set message format///</summary> public mailtypes mailtype {Get{return This.mailtype
   ;}
  Set{this.mailtype=value;} 
   ///<summary>///Get or set message body///</summary> public byte[] Mailbody {Get{return this.mailbody;}
  Set{this.mailbody=value;} }///<summary>///message encoding///</summary> public enum mailencodings {GB2312, ASCII, Unicode, UT F8}///<summary>///Message Format///</summary> public enum Mailtypes {Html, Text}///<summary>///SMTP Server Authentication method
  </summary> public enum Smtpvalidatetypes {///<summary>///do not need to validate///</summary> None, <summary>///General Auth Login Verification///</summary> Login,///<summary>///Universal Auth Plain Validation/ </summary> Plain,///<summary>///cram-md5 validation///</summary> CRAMMD5}///<SUMMARY&G
 T  Mail Send class///</summary> public class Ksn_smtp {#region ' member Fields '///<summary>///Connection Object///
  </summary> private TcpClient TC;
  <summary>///Network Flow///</summary> private NetworkStream ns;
  <summary>///Error code dictionary///</summary> private stringdictionary errorcodes=new stringdictionary (); <summary>///Response Code dictionary///</summary> private stringdictionary rightcodes=new stringdictionary after successful execution of the operation
  (); <suMmary>///the error message///</summary> private string errormessage= "";
  <summary>///record operation log///</summary> private string logs= ""; <summary>///Host login authentication mode///</summary> private stringcollection validatetypes=new stringcollection ()
  ;
  <summary>///NewLine constant///</summary> Private const string crlf= "\ r \ n";
  private string Servername= "SMTP";
  private string Logpath=null;
  private string Userid=null;
  private string Password=null;
  private string Mailencodingname= "GB2312";
  private bool Sendiscomplete=false;
  Private Smtpvalidatetypes Smtpvalidatetype=smtpvalidatetypes.login; #endregion #region "Propertys"///<summary>///get the last error message in the execution of this program///</summary> public string error
  message {Get{return this.errormessage;} ///<summary>///Gets or sets the log output path///</summary> public string LogPath {getting {return THIS.L
   Ogpath; } Set{this.logpath=value;}
  ///<summary>///Gets or sets the account number of the landing SMTP server///</summary> public string UserID {Get{return this.us
   Erid;}
  Set{this.userid=value;} ///<summary>///Gets or sets the password for the login SMTP server///</summary> public string Password {Get{return This.pas
   Sword;}
  Set{this.password=value;}
  ///<summary>///Gets or sets the authentication method to use the login SMTP server///</summary> public smtpvalidatetypes Smtpvalidatetype
   {Get{return this.smtpvalidatetype;}
  Set{this.smtpvalidatetype=value;} } #endregion #region "construct functions"///<summary>///Constructors///</summary>///<param Nam 
  e= "Server" > Host name </param>///<param name= "Port" > Port </param> Public ksn_smtp (string Server,int port)
   {tc=new tcpclient (server,port); NS=TC.
   GetStream ();
   This.servername=server;
  This.initialfields (); }///<summary>///constructor///</summary>///<param name= "IP" > host ip</param>/// Name= "Port" > Port </param> Public ksn_smtp (IPAddress ip,int port) {ipendpoint endpoint=new ipendpoint (ip,por
   T);
   Tc=new TcpClient (EndPoint); NS=TC.
   GetStream (); This.servername=ip.
   ToString ();
  This.initialfields (); #endregion #region "Methods" private void Initialfields ()//initialization connection {logs= "================" +datetime.now.tolo
   Ngdatestring () + "" +datetime.now.tolongtimestring () + "===============" +CRLF; Wrong status Code//**********************************
   Errorcodes.add ("421", "Service not ready, close transmission channel");
   Errorcodes.add ("432", "requires a password conversion");
   Errorcodes.add ("450", "requested mail operation not completed, mailbox is not available (such as: Mailbox Busy)");
   Errorcodes.add ("451", "abort required operation, required operation not executed");
   Errorcodes.add ("452", "insufficient system storage, required operation not completed");
   Errorcodes.add ("454", "Temporary certification failure");
   Errorcodes.add ("500", "Mailbox address Error");
   Errorcodes.add ("501", "parameter format error");
   Errorcodes.add ("502", "command not Implemented");
   Errorcodes.add ("503", "Order is not correct"); ErrorcOdes.
   ADD ("504", "Command parameter not implemented");
   Errorcodes.add ("530", "Need Authentication");
   Errorcodes.add ("534", "Authentication mechanism is too simple");
   Errorcodes.add ("538", "The current request authentication mechanism needs encryption");
   Errorcodes.add ("550", "The current mail operation is not completed, the mailbox is not available (for example, the mailbox is not found or the mailbox is not available)");
   Errorcodes.add ("551", "User not local, please try <forward-path>");
   Errorcodes.add ("552", "excess storage allocation, established operation not completed");
   Errorcodes.add ("553", "Mailbox name is not available, such as: Email address format error");
   Errorcodes.add ("554", "Transmission failure");
   Errorcodes.add ("535", "User authentication failed"); Status code//****************************** after the operation was successfully executed
   Rightcodes.add ("220", "Service Ready");
   Rightcodes.add ("221", "Service off transmission channel");
   Rightcodes.add ("235", "Validation Successful");
   Rightcodes.add ("250", "required mail operation complete");
   Rightcodes.add ("251", "non-local user, will forward to <forward-path>");
   Rightcodes.add ("334", "Server response verification Base64 string");
   Rightcodes.add ("354", "Start mail input, to <CRLF>.<CRLF> end");
   Read system response StreamReader Reader=new StreamReader (NS); Logs+=reader.
  ReadLine () +crlf; }///<summary> Send command to SMTP///</summary>///<param name= "cmd" ></param> private string SendCommand (string cmd, BOOL Ismaildata) {if (cmd!=null && cmd). Trim ()!=string.
    Empty) {byte[] cmd_b=null; 
    if (!ismaildata)//is not a mail data cmd+=crlf;
    Logs+=cmd;
     Start writing mail data if (!ismaildata) {cmd_b=encoding.ascii.getbytes (cmd); Ns.
    Write (cmd_b,0,cmd_b.length); else {cmd_b=encoding.getencoding (this.mailencodingname).
     GetBytes (CMD); Ns.
    BeginWrite (Cmd_b,0,cmd_b.length,new AsyncCallback (this.asynccallback), null);
    //Read server response StreamReader reader=new StreamReader (NS); String Response=reader.
    ReadLine ();
    Logs+=response+crlf; Check the status code string Statuscode=response.
    Substring (0,3);
    BOOL Isexist=false;
    BOOL Isrightcode=true;
      foreach (String err in This.errorCodes.Keys) {if (statuscode==err) {isexist=true;
      Isrightcode=false;
     Break } foreach (String rIght in This.rightCodes.Keys) {if (statuscode==right) {isexist=true;
     Break
    }/////The next action if (!isexist)//is not a legitimate SMTP host {This.seterror ("not a legitimate SMTP host, or server denial of service") based on the status code;
    The else if (!isrightcode)//command failed to execute successfully {This.seterror (statuscode+ ": +this.errorcodes[statuscode]);"
    else//command successfully executed {this.errormessage= "";
   return response;
   else {return null; }///<summary>///login via auth login SMTP server///</summary> private void Landingbylogin () {St Ring Base64userid=this.convertbase64string (this.
   UserID, "ASCII"); String Base64pass=this.convertbase64string (this.
   Password, "ASCII");
   Handshake This.sendcommand ("Helo" +this.servername,false);
   Start landing this.sendcommand ("Auth login", false);
   This.sendcommand (Base64userid,false);
  This.sendcommand (Base64pass,false); ///<summary>///via auth plain way landing server///</summary> private void LandingbypLain () {string null= ((char) 0).
   ToString (); String Loginstr=null+this. Userid+null+this.
   Password;
   String base64loginstr=this.convertbase64string (Loginstr, "ASCII");
   Handshake This.sendcommand ("Helo" +this.servername,false);
  Landing This.sendcommand (Base64loginstr,false);
   }///<summary>///through auth cram-md5 Way login///</summary> private void LandingByCRAMMD5 () {//handshake
   This.sendcommand ("Helo" +this.servername,false);
   Login string Response=this.sendcommand ("Auth cram-md5", false); Gets the identity string Identifier=response returned by the server.
   Remove (0,4);
   Using MD5 encryption to identify Ksn_mactripledes mac=new ksn_mactripledes (); Mac. Key=this.
   Password; Mac.
   Data=encoding.ascii.getbytes (identifier); String Hash=mac.
   Gethashvalue (); Send user account information This.sendcommand (this.
  Userid+ "" +hash,false); ///<summary>///Send mail///</summary>///<returns></returns> public bool SendMail (Mai
   Lmessage mail) {bool issended=true;
   try { Detect the necessary conditions for sending mail if (mail.
    Sender==null) {this.seterror ("no sender Installed"); } if (mail.
    receivers.count==0) {this.seterror ("At least one recipient"); } if (this. Smtpvalidatetype!=smtpvalidatetypes.none) {if (This.userid==null | | this.password==null) {THIS.SETERR
     Or ("The current setting requires SMTP authentication, but no login account is given"); //Start login switch (this.
      Smtpvalidatetype) {case SmtpValidateTypes.None:this.sendCommand ("Helo" +this.servername,false);
     Break
      Case SmtpValidateTypes.Login:this.landingByLogin ();
     Break
      Case SmtpValidateTypes.Plain:this.landingByPlain ();
     Break
      Case SmtpValidateTypes.CRAMMD5:this.landingByCRAMMD5 ();
     Break
    Default:break; ///Initialize mail session (corresponding to SMTP command mail) This.sendcommand ("Mail from:<" +mail.)
    sender+ ">", False); Identifies the recipient (corresponding to the SMTP command RCPT) foreach (string receive in mail.
    Receivers) {This.sendcommand ("rcpt to:<" +receive+ ">", False);
   } The identity begins to enter the message content (data) This.sendcommand ("Data", false); Start writing message content string message= "Subject:" +mail.
    Subject+crlf; message+= "X-mailer:" +mail.
    Xmailer+crlf;
    message+= "mime-version:1.0" +CRLF; if (mail. attachments.count==0)//No attachment {if (mail). Mailtype==mailtypes.text)//Text Format {message+= "Content-type:text/plain;" +crlf+ "". PadRight (8, "") + "charset=\" + Mail.
      Mailencoding.tostring () + "\" "+CRLF;
      message+= "Content-transfer-encoding:base64" +CRLF+CRLF; if (mail. Mailbody!=null) message+=convert.tobase64string (mail. Mailbody,0,mail. mailbody.length) +crlf+crlf+crlf+ "."
     +crlf; } else//html Format {message+= "content-type:multipart/alertnative;" +crlf+ "".
      PadRight (8, ') + "boundary" + "=\" =====003_dragon310083331177_=====\ "" +CRLF+CRLF+CRLF;
      message+= "This are a multi-part message in MIME format" +CRLF+CRLF;
      message+= "--=====003_dragon310083331177_=====" +CRLF; message+= "content-type:text/html;" +crlf+ "". PadRight (8,') + "charset=\" "+ Mail. Mailencoding.tostring ().
      ToLower () + "\" "+CRLF;
      message+= "Content-transfer-encoding:base64" +CRLF+CRLF; if (mail. Mailbody!=null) message+=convert.tobase64string (mail. Mailbody,0,mail.
      Mailbody.length) +crlf+crlf; message+= "--=====003_dragon310083331177_=====--" +crlf+crlf+crlf+ "."
     +crlf;
     The else//has attachments {//processing data for each attachment to be displayed in the message StringCollection attatchmentdatas=new stringcollection (); foreach (string path in mail.) Attachments) {if (!
      File.exists (Path)) {this.seterror ("specified attachment not found" +path);
       else {//get the byte stream of the attachment FileInfo file=new FileInfo (path);
       FileStream fs=new FileStream (path,filemode.open,fileaccess.read); if (fs. Length> (long) int.
       MaxValue) {This.seterror ("the size of the attachment exceeds the maximum limit"); } byte[] file_b=new byte[(int) fs.
       Length]; Fs.
       Read (file_b,0,file_b.length); Fs.
       Close (); String Attatchmentmailstr= "Content-type:apPlication/octet-stream; " +crlf+ "". PadRight (8, "") + "name=" + "\" "+file.
       Name+ "\" "+CRLF;
       attatchmentmailstr+= "Content-transfer-encoding:base64" +CRLF; attatchmentmailstr+= "content-disposition:attachment;" +crlf+ "". PadRight (8, "") + "filename=" + "\" "+file.
       Name+ "\" "+CRLF+CRLF;
       Attatchmentmailstr+=convert.tobase64string (file_b,0,file_b.length) +crlf+crlf;
      Attatchmentdatas.add (ATTATCHMENTMAILSTR); }//Set the message information if (mail. Mailtype==mailtypes.text)//Text Format {message+= "content-type:multipart/mixed;" +crlf+ "".
      PadRight (8, ') + "boundary=\" =====001_dragon320037612222_=====\ "" +CRLF+CRLF; message+= "This are a multi-part message in MIME format."
      +crlf+crlf;
      message+= "--=====001_dragon320037612222_=====" +CRLF; message+= "Content-type:text/plain;" +crlf+ "". PadRight (8, "") + "charset=\" "+mail." Mailencoding.tostring ().
      ToLower () + "\" "+CRLF;
      message+= "Content-transfer-encoding:base64" +CRLF+CRLF; if (mail. Mailbody!=null) message+=convert.tobase64string (mail. Mailbody,0,mail.
      Mailbody.length) +crlf;
      foreach (string s in Attatchmentdatas) {message+= "--=====001_dragon320037612222_=====" +CRLF+S+CRLF+CRLF; } message+= "--=====001_dragon320037612222_=====--" +crlf+crlf+crlf+ "."
     +crlf; else {message+= "content-type:multipart/mixed;" +crlf+ "".
      PadRight (8, ') + "boundary=\" =====001_dragon255511664284_=====\ "" +CRLF+CRLF; message+= "This are a multi-part message in MIME format."
      +crlf+crlf;
      message+= "--=====001_dragon255511664284_=====" +CRLF; message+= "content-type:text/html;" +crlf+ "". PadRight (8, "") + "charset=\" "+mail." Mailencoding.tostring ().
      ToLower () + "\" "+CRLF;
      message+= "Content-transfer-encoding:base64" +CRLF+CRLF; if (mail. Mailbody!=null) message+=convert.tobase64string (mail. Mailbody,0,mail.
      Mailbody.length) +crlf+crlf; for (int i=0;i<attatchmentdatas.count;i++) {message+= "--=====001_dragon255511664284_===== "+CRLF+ATTATCHMENTDATAS[I]+CRLF+CRLF; } message+= "--=====001_dragon255511664284_=====--" +crlf+crlf+crlf+ "."
     +crlf; }//Send mail data this.mailencodingname=mail.
    Mailencoding.tostring ();
    This.sendcommand (message,true);
   if (this.sendiscomplete) This.sendcommand ("QUIT", false);
   catch {issended=false;
    finally {this.disconnect (); The output log file if (this.
     Logpath!=null) {FileStream fs=null; If File.exists (this. LogPath)) {fs=new FileStream (this.
      Logpath,filemode.append,fileaccess.write);
     This.logs=crlf+crlf+this.logs; else Fs=new FileStream (this.
     Logpath,filemode.create,fileaccess.write); Byte[] logpath_b=encoding.getencoding ("gb2312").
     GetBytes (This.logs); Fs.
     Write (logpath_b,0,logpath_b.length); Fs.
    Close ();
  } return issended;
  ///<summary>///Asynchronous Write Data///</summary>///<param name= "Result" ></param>private void AsyncCallback (IAsyncResult result) {if, result.
  iscompleted) This.sendiscomplete=true; ///<summary>///Close connection///</summary> private void disconnect () {try {ns.
    Close (); Tc.
   Close ();
   catch {; }///<summary>///settings Error action///</summary>///<param name= "ERRORSTR" ></param> PR
   ivate void SetError (String errorstr) {this.errormessage=errorstr;
   logs+=this.errormessage+crlf+ "" Message Processing Action abort "" +CRLF;
   This.disconnect ();
  throw new ApplicationException (""); ///<summary>///converts strings to base64///</summary>///<param name= "str" ></param>///<p Aram Name= "Encodingname" ></param>///<returns></returns> private String convertbase64string ( String str,string encodingname) {byte[] str_b=encoding.getencoding (encodingname).
   GetBytes (str);
  Return convert.tobase64string (str_b,0,str_b.length); } #endregion}} 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.