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}}