The email is sent in web applications. It is not uncommon in the ASP era. Everyone is to use some third-party components such as Jmail, ASPMAIL, etc. to send mail. Since Microsoft launched the ASP.NET, many programmers began to turn into C # as the main development language. ASP.NET provides a more powerful feature, and it is also available to everyone an SMTP class as a mail transmission. However, with the extensive spread of spam, many mail service providers have added SMTP certification procedures, which is ESMTP, and Microsoft's SMTP classes do not support authentication. Of course, some solutions are now available, using other means to issue authentication information. But I think, is there anything better? In order to solve this problem, the author does not think about the two-day tea, and the day is finally found :). Below, we will use TCPClient to send mail to the SMTP server communication.
In fact, the principle is to use sockets and servers to communicate, follow the SMTP protocol, and connect to the server. Some mail components we use are doing this.
Before starting, we have a preliminary understanding of the SMTP protocol and its extended ESMTP.
Some major command formats of SMTP and ESMTP have the following:
Helo
This is equivalent to gree consumption with the server, hello, I am a certain
EHLO
This is a contact method for the ESMTP server, you must enter this command, the system will start the authentication program
Auth login
Enter this command, the system's authentication program will start, and the system will return a string that has been processed through the base64, meaning "Please enter your username". The username must then be sent to the server, and the username must also pass the Base64 encoded conversion. The server will require the input password after the authentication of the username. At this time, the password after the Base64 encoded conversion is input. After success, you can run the following command.
Mail from:
This is the email address telling the server sender.
RCPT TO:
This is the email address telling the server recipient.
Data
After entering this command, the server officially begins to accept data.
.
After the data is completed, you must enter a command ".", The server will stop the acceptance of the data.
Quit Exit System
The above is a description of some basic orders. If you still have anything you don't understand, you can refer to TCP / IP-related books, or you can see the RFC document: http://210.25.132.18/rfc/index.html
Now we officially start, see how to work in C #.
Step 1: Create a class, named mailsend, this class inherits system.net.sockets.tcpclient
Using system;
Using system.net.sockets; // for processing network connection
Using system.io; // for processing attachments
Using system.text; // for processing text encoding
Using system.data;
Using system.net;
Public class mailsend: tcpclient
{
Public mailsend () PUBLIC MAILSEND ()
{
}
}
Here I want to talk about TCPClient, its main role is to provide client connection for TCP network services. You can see that he is from Sockets package, which is actually based on Socket class. However, he provides TCP services at a higher abstraction, and it is easier to operate. Step 2: Establish some basic variables and connection methods
1, basic variable
Private string server; // SMTP server domain name
Private Int port; // port
Private string username; // username
Private string password; // password
Private string subject; // theme
Private string body; // text content
Private string htmlbody; // hypertext content
Private string from; // sender address
Private string to; // recipient address
Private string fromname; // send a name
Private string toname; // Remarks Name
Private string content_type; // mail type
Private string encode; // message code
Private string charset; // Language code
Private DataTable fileList; // Annex list
Private int priority; // mail priority
The above definitions are all basic information required for mail transmission, and the above variables can be passed as attributes.
Such as:
Public String SMTPServer
{
Set {this.server = value;
}
This is also the case.
2. Method for writing commands to the server
Variable strcmd is a string of commands or data that needs to be entered
Variable Charset is the character language of the data, which can be set to GB2312
Private void WriteStream (String strcmd, string chars)
{
Stream tcpstream; // Define the operation object
Strcmd = strcmd "/ r / n"; // joining a newline
TcpStream = this.getStream (); // Get data stream
// Translate the command line to Byte []
Byte [] BWRITE = Encoding.Getencoding (charset) .getbytes (STRCMD.TOCHARRAY ());
// Since the size of each write is limited, then we will set the length of the data written to 75 bytes, once the command length exceeds 75, step by step.
INT start = 0;
INT length = bwrite.length;
INT Page = 0;
INT size = 75;
INT count = size;
IF (Length> 75)
{
// Data Page
IF ((Length / size) * size
Page = Length / size 1;
Else
Page = Length / size;
For (int i = 0; i
{
START = i * size;
IF (i == Page-1)
Count = Length- (i * size);
TcpStream.write (BWRITE, START, Count); // Write data to the server
}
}
Else
TcpStream.write (BWRITE, 0, BWRITE.LENGTH);
}
Catch (Exception)
{}
}
In this method, our final use is the most important thing is TCPStream.Write (), and the data pane is only written step by step. In addition, when writing data, the string must be converted to a BYTE [] type. Here I use the Stream object, and you can also use the NetWorkStream object to operate, the actual effect is consistent. In the following return information, I used NetWorkStream. In fact, this is also a process that helps you have familiar with the current operation object. 3, get the return information of the server
Private string receiveStream ()
{
String sp = NULL;
Byte [] by = new byte [1024];
NetworkStream ns = this.getStream (); // You can get the back data stream of the server here
INT size = ns.read (by, 0, by.length); // read the data stream
IF (size> 0)
{
sp = encoding.default.getstring (by); // Translate to String
}
Return SP;
}
After entering the data command, the rest of the time sends a command to the server, the server returns some information, and there is a status code to return, telling you whether the operation is successful. Once the data command is input, the server will not return any information until the server will return, until "." End passes, the server returns information.
4. Send a command and judge whether the return information is correct, that is, whether the issued command server is accepted and passed.
This method actually combines the above two methods to use, one write, one receiving, and then judge, see if it is correct. This way we can monitor whether each step is working properly.
The parameter strCMD is also a command or data that needs to be entered.
The parameter state is the status code that the operation is successful.
Private Bool OperaStream (String Strmd, String State)
{String sp = null;
Bool Success = FALSE;
Try
{
WriteStream (strcmd); // Write command
sp = receiveStream (); // Accept return information
IF (sp.indexof (state)! = - 1) // Decision status code is correct
Success = true;
}
Catch (Exception EX)
{Console.Write (ex. TString ());
RETURN SUCCESS;
}
When we perform each step, we are determined by the status code to determine whether it is successful, then if the operation is successful, it will return the correct status code. According to this principle, we enter the command and indicate the status of successful operation. The code, by the acquisition data judgment returned whether it is not the correct status code to determine whether the next step is proceed.
Here I want to tell you some of the basic code expressed.
211 Help return system status
214 Help Information
220 service is ready
221 close connection
250 request operation
251 users are not locally, forwarded
354 starting mail input
421 service is not available
450 operation is not executed, the mailbox is busy
451 operation suspension, local error
452 operation is not performed, the storage space is insufficient
500 command is unrecognizable or syntax
501 parameter syntax
502 command does not support
503 command order
504 Command parameters do not support
550 operation is not executed, the mailbox is not available
551 non-local users
552 suspension, storage space is insufficient
553 operation is not executed, the mailbox name is incorrect 554 transmission failed
Through the basic methods of the above, we can start connecting to the server. Since both SMTP and ESMTP have both SMTP and ESMTP, different server connections are different, then we need to complete a method to get the server.
Public bool getmailserver ()
{
Try
{
//DNS
System.net.ipaddress ipaddress = (ipaddress) System.net.dns.resolve (this.server) .addresslist.getValue (0);
System.net.IpendPoint Endpoint = New IpendPoint (iPadDress, 25);
Connect (endpoint); / / Connect the SMTP server
ReceiveStream (); // Get connection information
IF (this.username! = null)
{
// Start server authentication
// If the status code is 250, the operation is successful.
IF (! "" Ehlo LocalHost "," 250 "))
{
THIS.CLOSE ();
Return False;
}
IF (! OperaStream ("Auth login", "334"))
{
THIS.CLOSE ();
Return False;
}
Username = authstream (username); // converts UserName to Base64 yards here
IF (! OperaStream (this.username, "334"))
{
THIS.CLOSE ();
Return False;
}
Password = authstream (password); // Convert Password to Base64 yards here
IF (! OperaStream (this.password, "235"))
{
THIS.CLOSE ();
Return False;
}
Return True;
}
Else
{// If the server does not require authentication
IF (OperaStream ("Helo LocalHost", "250"))
{
Return True;
}
Else
{
Return False;
}
}
}
Catch (Exception EX)
{Return False;}
}
The above method is mainly used in contact with the server, which contains a connection method for two different servers. If the username is not empty, then we first perform an ESMTP connection, otherwise we and the server directly acquires contact. When ESMTP is connected, the username and password must be BASE64 encoding, otherwise the server will not be recognized.
Private string authstream (String strcmd)
{
Try
{
Byte [] by = encoding.default.getbytes (STRCMD.TOCHARRAY ());
Strcmd = convert.tobase64string (by);
}
Catch (Exception EX)
{Return EX.TOSTRING ();
Return strcmd;
}
The above method converts the data to the Base64 encoded string, everyone feel too abstract, can try it this way, enter Telnet SMTP.sohu.com 25 in the CMD mode and then enter the way, you can connect SOHU's SMTP server, Sohu The SMTP server adopts the ESMTP protocol, must be certified, you can try it.
Step 3: About annex pass on mail
When you have sent an email, sometimes you will contain some attachments, then this component also takes into account this. Below we will tell how to process filelist = new data on attachments (//); // Defined variables, initialization operations
FileList.columns.add (New Datacolumn ("FileName", TypeOf (String))))); // File Name
FileList.columns.add (New Datacolumn ("FileContent", TypeOf (String))); // File content
Public void loadattfile (String Path)
{
/ / Read the file stream according to the path
FILESTREAM FSTR = New FileStream (path, filemode.open); // Establish a file stream object
Byte [] by = new byte [convert.toint32 (fstr.length)];
fstr.read (by, 0, by.length); // Read file content
FSTR.CLOSE (); // Close
// format conversion
String fileinfo = convert.tobase64string (by); // Translate into Base64 encoding
/ / Add to the file table
DataRow Dr = filelist.newrow ();
DR [0] = path.getFileName (PATH); // Get file name
DR [1] = fileInfo; // file content
FileList.Rows.Add (DR); // increase
}
Through this method, the content information of the file will be directly read, and then stored in the DataTable object, theoretically read countless files, of course, the larger the file, the longer the transmission time. This method is only for local accessories. If you are interested, you can use HttpRequest to make a program captured online file, directly capture the files on the Internet, but in general, this method is rarely used. Ok, gossip doesn't talk, we have read the files, then how to deal with it? Please see a method below.
1: Private void attachment ()
2: {// Do a loop on the file list
3: for (int i = 0; i
4: {
5: DATAROW DR = filelist.rows;
6: WriteStream ("- unique-boundary-1"); // mail content separator
7: WriteStream ("Content-Type: Application / OCTET-stream; Name = /" " DR [0] .tostring () " / "); // file format
8: WriteStream ("Content-Transfer-Encoding: Base64"); // Code
9: WriteStream ("Content-Disposition: attachment; filename = /" " DR [0] .tostring () " / "); // file name
10: WriteStream ("");
11: String fileinfo = DR [1] .tostring ();
12: WriteStream (fileInfo); // Write the contents of the file
13: WriteStream (""); 14:}
15:}
In this method, we use the WritestReam () method. You may see some confused, as if there is no headless, actually this section, will write after the header information of the message and the text content will be written again. On the server, you can see the front part in the program below. Then in the code of the code, expressed the type of file, I used a lazy way, using Application / OcTet-stream instead of all file types, in fact, there is a format for most common files. Everyone can judge according to the extension of its file name, here I give other formats.
Extension format
".gif" ---> "image / gif"
".gz" ---> "Application / X-Gzip"
".htm" ---> "text / html"
".html" ---> "text / html"
".jpg" ---> "image / jpeg"
".tar" ---> "Application / X-TAR"
".txt" ---> "text / plain"
".zip" ---> "Application / Zip"
I am relatively lazy. If you have a friend you need, you can make up some judgments, get the original format of the file.
Step 4: About the header information of the mail
I have talked so much, just like a dessert before eating a big meal. Now we have to enter the most important part - the header information of the mail, in fact, this thing we have seen very much, everyone is sending and receiving emails, Viewing the properties of the email will see a large string code, there are some email addresses, what is the IP address, this is the header information of the mail.
The basic content of the header information is now on:
From:
TO:
Subject:
Date:
Reply-to:
Content-Type:
X-Priority:
MIME-VERSION:
Content-Transfer-Encoding:
X-MAILER:
If you have installed Outlook (generally install :)), send yourself a letter, after receiving, check the property, then see the data containing some of the information above, everyone can be based on the header information of Outlook Reference. Here, I have to say that the content-type information is the header information. In fact, we often contain text content, HTML hypertext content, and attachment content when sending. Then, the format of the message is Multipart / Mixed, but So many things you want to put it all, the server does not know, then add a separator between different content, and then add another end separator after it is over, there is a bit like HTML. In the case of Content-Type, there is a sentence boundary = unique-boundary-1, here is the name of my separator. So in one email, there can be multiple separators, and the remaining separators are actually extended at the first separator you give. Said so much, look at the program:
WriteStream ("Date:" DateTime.now); // Time
WriteStream ("from:" this.fromname <" this.from "> "); // sender
WriteStream ("Subject:" this.subject); // Theme
WriteStream ("to:" this.to); // Recipient
// mail format
WriteStream ("Content-Type: Multipart / Mixed; Boundary = /" Unique-Boundary-1 / ");
WriteStream ("reply-to:" this.from); // Reply address
WriteStream ("x-priority:" priority); // Priority
WriteStream ("MIME-VERSION: 1.0"); // MIME version
// Data ID, random
WriteStream ("Message-ID:" DateTime.now.tofiletime () "@ security.com");
WriteStream ("Content-Transfer-Encoding:" this.Encode); // Content Code
WriteStream ("X-MAILER: DS Mail Sender V1.0"); // Mail sender
WriteStream ("");
Take a look at this section of information, the variables inside are defined in advance. When the header is ended, write an empty message, so the SMTP server will think that you have already written.
Writestream (Authstream ("This Is A Multi-Part Message In Mime Format."));
WriteStream ("");
Here is just one end descriptive content.
/ / Separation input from this point
WriteStream ("- unique-boundary-1);
/ / Define the second separator here
WriteStream ("Content-Type: Multipart / Alternative; Boundary = /" Unique-Boundary-2 / ");
WriteStream (""); // Text information
WriteStream ("- unique-boundary-2");
WriteStream ("Content-Type: Text / Plain; Charset =" this.charset);
WriteStream ("Content-Transfer-Encoding:" this.Encode);
WriteStream ("");
Writestream (body);
WriteStream (""); // Write as empty information after a part is written, segmentation
// HTML information
WriteStream ("- unique-boundary-2");
WriteStream ("Content-Type: Text / Html; Charset =" this.charset);
WriteStream ("Content-Transfer-Encoding:" this.Encode);
WriteStream ("");
WriteStream (HTMLBody);
WriteStream ("");
WriteStream ("- unique-boundary-2 -"); // The end symbol of the separator, there are more than the tail -
WriteStream ("");
// increase accessories
Attachment (); // This method is what we have ticked here, in fact, he put it here.
WriteStream ("");
WriteStream ("- unique-boundary-1--")
IF (! ") // Finally, enter". "
{
this.close (); // Close connection
}
This is the core part of an email. The above variables are defined global variables, passed by the user to the object. The main content of the entire mail component is here. The fingers are knocking, because the level is limited, some places are not satisfied, and apologize here. Before studying the mail, searching information online, but there is no gain. It seems that everyone is willing to put the experience in the belly. Since my stomach is not strong enough, I hope to share this meal with you. Finally, let's see how it is applied.
Quote in an ASPX file or other CS file:
Mailsend ms = new mailsend (); // Constructive
Ms.smtpserver = "smtp.sohu.com"; // Transfer parameters
......
Ms.send (); // Send Mail
In this article, I didn't give a complete code, but just gave a code snippet, but this is enough to sort out the entire program. The purpose of this is to do not want everyone to see it directly, I hope to see it clearly, understand the content of them, this is helpful for improving my own level. The mail is always a problem that is more troublesome, especially after adding the certification process, speed is slow, so I want a lot of mail group software to support SMTP mail, etc. I have time, maybe I will do it. SMTP email sending components take it out and share it.