Create Mail Transfer Components (SMTP) using C #

xiaoxiao2021-03-06  58

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 Helo Localhost

This is equivalent to gree consumption with the server, hello, I am a certain

EHLO Ehlo Localhost

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: , for example: mail from: webmaster@sina.com

This is the email address telling the server sender.

RCPT TO: For example: rcpt to: webmaster@sina.com

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: Format: from: Administrator

TO: Format: TO: Aquatic Month <1234@sina.com>

Subject: Format: Subject: Today's weather is very good!</p> <p>Date: <Time> Format: Date: THU, 29 AUG 2002 09:52:47 0800 (CST)</p> <p>Reply-to: <email address> format: reply-to: Webmaster@sina.com</p> <p>Content-Type: <Mail Type> Format: Content-Type: Multipart / Mixed; Boundary = Unique-Boundary-1</p> <p>X-Priority: <Mail Priority> Format: X-Priority: 3</p> <p>MIME-VERSION: <version> format: Mime-Version: 1.0</p> <p>Content-Transfer-Encoding: <Content Transport Code> Format: Content-Transfer-Encoding: Base64</p> <p>X-MAILER: <Mail Sender> Format: X-MAILER: Foxmail 4.0 Beta 1 [CN]</p> <p>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:</p> <p>WriteStream ("Date:" DateTime.now); // Time</p> <p>WriteStream ("from:" this.fromname <" this.from "> "); // sender</p> <p>WriteStream ("Subject:" this.subject); // Theme</p> <p>WriteStream ("to:" this.to); // Recipient</p> <p>// mail format</p> <p>WriteStream ("Content-Type: Multipart / Mixed; Boundary = /" Unique-Boundary-1 / ");</p> <p>WriteStream ("reply-to:" this.from); // Reply address</p> <p>WriteStream ("x-priority:" priority); // Priority</p> <p>WriteStream ("MIME-VERSION: 1.0"); // MIME version</p> <p>// Data ID, random</p> <p>WriteStream ("Message-ID:" DateTime.now.tofiletime () "@ security.com");</p> <p>WriteStream ("Content-Transfer-Encoding:" this.Encode); // Content Code</p> <p>WriteStream ("X-MAILER: DS Mail Sender V1.0"); // Mail sender</p> <p>WriteStream ("");</p> <p>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.</p> <p>Writestream (Authstream ("This Is A Multi-Part Message In Mime Format."));</p> <p>WriteStream ("");</p> <p>Here is just one end descriptive content.</p> <p>/ / Separation input from this point</p> <p>WriteStream ("- unique-boundary-1);</p> <p>/ / Define the second separator here</p> <p>WriteStream ("Content-Type: Multipart / Alternative; Boundary = /" Unique-Boundary-2 / ");</p> <p>WriteStream (""); // Text information</p> <p>WriteStream ("- unique-boundary-2");</p> <p>WriteStream ("Content-Type: Text / Plain; Charset =" this.charset);</p> <p>WriteStream ("Content-Transfer-Encoding:" this.Encode);</p> <p>WriteStream ("");</p> <p>Writestream (body);</p> <p>WriteStream (""); // Write as empty information after a part is written, segmentation</p> <p>// HTML information</p> <p>WriteStream ("- unique-boundary-2");</p> <p>WriteStream ("Content-Type: Text / Html; Charset =" this.charset);</p> <p>WriteStream ("Content-Transfer-Encoding:" this.Encode);</p> <p>WriteStream ("");</p> <p>WriteStream (HTMLBody);</p> <p>WriteStream ("");</p> <p>WriteStream ("- unique-boundary-2 -"); // The end symbol of the separator, there are more than the tail -</p> <p>WriteStream ("");</p> <p>// increase accessories</p> <p>Attachment (); // This method is what we have ticked here, in fact, he put it here.</p> <p>WriteStream ("");</p> <p>WriteStream ("- unique-boundary-1--")</p> <p>IF (! ") // Finally, enter". "</p> <p>{</p> <p>this.close (); // Close connection</p> <p>}</p> <p>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.</p> <p>Quote in an ASPX file or other CS file:</p> <p>Mailsend ms = new mailsend (); // Constructive</p> <p>Ms.smtpserver = "smtp.sohu.com"; // Transfer parameters</p> <p>......</p> <p>Ms.send (); // Send Mail</p> <p>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.</p></div><div class="text-center mt-3 text-grey"> 转载请注明原文地址:https://www.9cbs.com/read-111833.html</div><div class="plugin d-flex justify-content-center mt-3"></div><hr><div class="row"><div class="col-lg-12 text-muted mt-2"><i class="icon-tags mr-2"></i><span class="badge border border-secondary mr-2"><h2 class="h6 mb-0 small"><a class="text-secondary" href="tag-2.html">9cbs</a></h2></span></div></div></div></div><div class="card card-postlist border-white shadow"><div class="card-body"><div class="card-title"><div class="d-flex justify-content-between"><div><b>New Post</b>(<span class="posts">0</span>) </div><div></div></div></div><ul class="postlist list-unstyled"> </ul></div></div><div class="d-none threadlist"><input type="checkbox" name="modtid" value="111833" checked /></div></div></div></div></div><footer class="text-muted small bg-dark py-4 mt-3" id="footer"><div class="container"><div class="row"><div class="col">CopyRight © 2020 All Rights Reserved </div><div class="col text-right">Processed: <b>0.036</b>, SQL: <b>9</b></div></div></div></footer><script src="./lang/en-us/lang.js?2.2.0"></script><script src="view/js/jquery.min.js?2.2.0"></script><script src="view/js/popper.min.js?2.2.0"></script><script src="view/js/bootstrap.min.js?2.2.0"></script><script src="view/js/xiuno.js?2.2.0"></script><script src="view/js/bootstrap-plugin.js?2.2.0"></script><script src="view/js/async.min.js?2.2.0"></script><script src="view/js/form.js?2.2.0"></script><script> var debug = DEBUG = 0; var url_rewrite_on = 1; var url_path = './'; var forumarr = {"1":"Tech"}; var fid = 1; var uid = 0; var gid = 0; xn.options.water_image_url = 'view/img/water-small.png'; </script><script src="view/js/wellcms.js?2.2.0"></script><a class="scroll-to-top rounded" href="javascript:void(0);"><i class="icon-angle-up"></i></a><a class="scroll-to-bottom rounded" href="javascript:void(0);" style="display: inline;"><i class="icon-angle-down"></i></a></body></html><script> var forum_url = 'list-1.html'; var safe_token = 'BxMELzcdZ_2B11GDKcorQ1n8qVgQ0qrADJ29uHg8n8ei_2FrYbWYHlS_2BM4e8pmgfBntqs81BanLN8Q7DjpRi7QP2pA_3D_3D'; var body = $('body'); body.on('submit', '#form', function() { var jthis = $(this); var jsubmit = jthis.find('#submit'); jthis.reset(); jsubmit.button('loading'); var postdata = jthis.serializeObject(); $.xpost(jthis.attr('action'), postdata, function(code, message) { if(code == 0) { location.reload(); } else { $.alert(message); jsubmit.button('reset'); } }); return false; }); function resize_image() { var jmessagelist = $('div.message'); var first_width = jmessagelist.width(); jmessagelist.each(function() { var jdiv = $(this); var maxwidth = jdiv.attr('isfirst') ? first_width : jdiv.width(); var jmessage_width = Math.min(jdiv.width(), maxwidth); jdiv.find('img, embed, iframe, video').each(function() { var jimg = $(this); var img_width = this.org_width; var img_height = this.org_height; if(!img_width) { var img_width = jimg.attr('width'); var img_height = jimg.attr('height'); this.org_width = img_width; this.org_height = img_height; } if(img_width > jmessage_width) { if(this.tagName == 'IMG') { jimg.width(jmessage_width); jimg.css('height', 'auto'); jimg.css('cursor', 'pointer'); jimg.on('click', function() { }); } else { jimg.width(jmessage_width); var height = (img_height / img_width) * jimg.width(); jimg.height(height); } } }); }); } function resize_table() { $('div.message').each(function() { var jdiv = $(this); jdiv.find('table').addClass('table').wrap('<div class="table-responsive"></div>'); }); } $(function() { resize_image(); resize_table(); $(window).on('resize', resize_image); }); var jmessage = $('#message'); jmessage.on('focus', function() {if(jmessage.t) { clearTimeout(jmessage.t); jmessage.t = null; } jmessage.css('height', '6rem'); }); jmessage.on('blur', function() {jmessage.t = setTimeout(function() { jmessage.css('height', '2.5rem');}, 1000); }); $('#nav li[data-active="fid-1"]').addClass('active'); </script>