Keyword: VC ++ SMTP protocol Email Delivery analysis this article introduces a method to implement Email Delivery in a program using SMTP protocol specifications and using SMTP protocol commands directly. Some key implementation code is provided in the VC ++ development environment.
Preface
As the most widely used and most widely used service item on the Internet, email service has been widely used and plays a very important role in network applications. Like other network services, the email system also uses transmission protocols, including SMTP (Simple Mail Transfer Protocol, Simple Mail Transfer Protocol), POP (Post Office Protocol, Post Office Protocol) and IMAP (Internet Message Access Protocal, Message Access Protocol). These protocols are used to send and receive emails. Some mail processing software such as OutLook Express and FoxMail are designed to send and receive mail based on SMTP and POP3 protocols combined with Windows Sockets. This article takes the SMTP protocol as the research object. In the Visual C ++ 6.0 programming environment, the SMTP command is sent through a socket based on the SMTP protocol to receive and process the feedback from the mail server, this allows you to send emails.
SMTP communication model and session Process
SMTP Communication Model
SMTP is a member of the TCP/IP protocol family. It specifies how to transfer an email from the sender address to the receiver address, that is, the transmission rules. The SMTP communication model is not complex. It mainly focuses on sending SMTP and receiving SMTP. First, a duplex communication link is established for sending SMTP to receive SMTP mail requests, the receiving SMTP here is relative to sending SMTP. In fact, it can be either the final receiver or intermediate transmitter. Sending SMTP is responsible for sending SMTP commands to the receiving SMTP, while receiving SMTP is responsible for receiving and responding. The following communication model can be used for representation in general:
SMTP commands and responses
From the preceding communication model, we can see that the SMTP Protocol completes the session between sending SMTP and receiving SMTP by sending SMTP commands and receiving SMTP feedback responses. After the communication link is established, send the smtp mail command to send the mail sender. If you receive SMTP, you can receive the mail at this time and then make an OK response, then, send SMTP to continue issuing the RCPT command to confirm whether the email is received. If yes, an OK response will be made; otherwise, a rejected response will be sent, but this will not affect the entire email operation. Both parties repeatedly until the email is processed. The SMTP protocol contains 10 SMTP commands. The list is as follows:
SMTP command |
Command description |
Hello <domain> <CRLF> |
Identify a hello Command sent by the sender to receive SMTP |
Mail from: <reverse-path> <CRLF> |
<Reverse-path> is the sender address. This command informs the recipient of the start of sending a new mail and initializes all statuses and buffers. This command starts a mail transmission process and finally delivers mail data to one or more mailboxes. |
Rcpt to: <forward-path> <CRLF> |
<Forward-path> identifies the addresses of each email recipient |
Data <CRLF> |
After receiving SMTP, the behavior is treated as mail data, ending with <CRLF>. <CRLF> identifying data. |
Rest <CRLF> |
Exit/reset the current email transmission |
Noop <CRLF> |
Only the OK response is required for receiving SMTP. (For testing) |
Quit <CRLF> |
It is required to receive an OK response from SMTP and disable transmission. |
VRFY <string> <CRLF> |
Verify whether the specified email address exists. this command is not allowed on the server due to security reasons. |
EXPN <string> <CRLF> |
Check whether the specified mailbox list exists and expand the mailbox list. |
Help <CRLF> |
Query commands supported by the server |
Note: <CRLF> the carriage return and line feed are supported, and the ASCII code is 13 and 10 (decimal), respectively ).
Each SMTP command returns a response code. Each number of the response code has a specific meaning. For example, if the first number is 2, the command is successful; if the number is 5, the command fails; table 3 is not complete. Some Complex email programs use this feature to first check the first number of the response code and determine the next action based on the value. The following lists the SMTP response codes:
Response Code |
Description |
501 |
Parameter format Error |
502 |
Commands cannot be implemented |
503 |
Wrong command sequence |
504 |
Command parameters cannot be implemented |
211 |
System status or system help response |
214 |
Help Information |
220 |
<Domain> Service ready |
221 |
<Domain> service Shutdown |
421 |
<Domain> the service is not ready. Disable the transmission channel. |
250 |
The required email operation is completed. |
251 |
The user is not local and will forward to <forward-path> |
450 |
The requested email operation is incomplete and the email address is unavailable |
550 |
The requested email operation is incomplete and the email address is unavailable |
451 |
Discard required operations; errors occurred during processing |
551 |
The user is not local. Please try <forward-path> |
452 |
The operation is not executed because the system storage is insufficient. |
552 |
Excessive storage allocation, required operations not performed |
553 |
The mailbox name is unavailable and the required operation is not performed |
354 |
Start email input, ended "." |
554 |
Operation failed |
Use SMTP protocol in applications
SMTP session Process
Before program design, it is necessary to clarify the session process of the SMTP protocol. In fact, the content described above can roughly outline the framework for sending mails using SMTP. For a common mail, the process is roughly as follows: first establish a TCP connection, then the client sends a hello command to identify the sender and continues sending mail commands by the client, for example, the server responds as "OK ", you can continue to send the RCPT command to identify the recipient of the email. Here there can be multiple RCPT lines, and the server side indicates whether the email is willing to be accepted by the recipient. After the negotiation, both parties send the email with the command data, and send the "." indicating the end of the email together. Then, the sending process is ended and the quit command is used to exit. The following describes the session process in more detail and intuitively From the langrui@sohu.com to the renping@sina.com through an instance:
R: 220 Sina.com Simple Mail Transfer Service ready S: Hello sohu.com R: 250 Sina.com S: mail from: <langrui@sohu.com> R: 250 OK S: rcpt to: <renping@sina.com> R: 250 OK S: Data R: 354 start mail input; end with "<CRLF>. <CRLF>" S :...... R: 250 OK S: Quit R: 221 Sina.com Service closing transmission channel |
Mail formatting
Because of the special structure of the email, it cannot be directly processed as a simple text during transmission, the mail header and body must be formatted to be sent. The main elements to be formatted include the sender address, recipient address, subject, and sending date. In RFC 822, you can describe how to format an email. For more information, see this document. The following section uses VC ++ 6.0 to write the formatted email as follows (part of the Code) in accordance with RFC 822 documentation ):
// Prepare the email header Strtemp = _ T ("from:") + m_strfrom; file: // sender address Add_header_line (lpctstr) strtemp ); Strtemp = _ T ("to:") + m_strto; file: // recipient address Add_header_line (lpctstr) strtemp ); M_tdatetime = m_tdatetime.getcurrenttime (); // sending time Strtemp = _ T ("data :"); Strtemp + = m_tdatetime.format ("% A, % d % B % Y % H: % m: % S % Z "); Add_header_line (lpctstr) strtemp ); Strtemp = _ T ("Subject:") + m_strsubject; file: // topic Add_header_line (lpctstr) strtemp ); File: // end of the mail header M_strHeader + = _ T ("rn "); File: // prepare the email body If (m_strBody.Right (2 )! = _ T ("rn") file: // confirm that the last line is ended with a carriage return. M_strBody + = _ T ("rn "); |
Here, the add_header_line (lpctstr szheaderline) function is used to append the string indicated by szheaderline to the end of m_strheader. The formatted header is saved in m_strheader, And the formatted body is saved in m_strbody.
The Socket socket provides the network communication basis for SMTP
Many network programs are implemented using Socket sockets. Programming of some standard network protocols, such as HTTP, FTP, and SMTP, is also based on socket programs, only the port number is no longer randomly set but must be specified by the Protocol. For example, the http port is 80, the ftp port is 21, and the SMTP port is 25. The socket only provides the communication capability on the network with the specified server on the specified port. The network protocol specifies how the customer communicates with the server, this is completely transparent to sockets. Therefore, you can use the Socket socket to provide network communication capabilities for the program. For the Network Communication Connection established, what kind of communication response should be implemented according to the provisions of the SMTP protocol. Socket socket network programming articles are rich in materials, limited by the length of this article, I will not go into details here, please refer to the relevant documentation for details. For the sake of simplicity, we did not compile complicated Windows Sockets APIs for programming. Instead, we used the csocket class of MFC, which had been well encapsulated. Before using a socket, you must first initialize the socket with the afxsocketinit () function, and then create a socket object with create (). Then, the socket uses connect () establish a connection with the email server. If everything works normally, follow the SMTP protocol to use send () and receive () function to send the SMTP command and receive the response code sent from the mail server to complete the transfer of the mail.
Implementation of SMTP session response
After establishing a link connection with the mail server, you can design the program according to the previously described session process. For sending SMTP commands, you can send the group frames to the server using the send () function of the csocket class after the group frames are completed in the command format, and receive the response code sent from the mail server using the receive () function of the csocket class, it also responds to the SMTP protocol according to the response code table. The following is part of the implementation code of the GET_RESPONSE () function used to receive the response code:
Bool csmtp: get_response (UINT response_expected) // The input parameter is the desired response code. { ...... // M_wsSMTPServer is a CSocket Class Object. Call Receive () to Receive the response code to the cache. // Response_buf M_wsSMTPServer.Receive (response_buf, RESPONSE_BUFFER_SIZE) SResponse = response_buf; Sscanf (LPCTSTR) sResponse. Left (3), _ T ("% d"), & response ); PResp = & response_table [response_expected]; File: // check whether the received response code is expected If (response! = PResp-> nResponse) { ...... // Handle errors if they are not equal Return FALSE; } Return TRUE; } |
Each part of a session is similar. It is a command-response method, and is displayed as a pair, the following is the focus of this article and the key part of implementation-formatting the SMTP command and sending the command and checking and processing the response code of the mail server under program control:
// Format and send the HELLO command, and receive and verify the server response code Gethostname (local_host, 80 ); SHello. Format (_ T ("HELO % srn"), local_host ); M_wsSMTPServer.Send (LPCTSTR) sHello, sHello. GetLength ()); If (! Get_response (GENERIC_SUCCESS) file: // check whether the response code is 250 { ...... Return FALSE; } File: // format and send the MAIL command, and receive and verify the server response code SFrom. Format (_ T ("MAIL From: <% s> rn"), (LPCTSTR) msg-> m_strFrom ); M_wsSMTPServer.Send (LPCTSTR) sFrom, sFrom. GetLength ()); If (! Get_response (GENERIC_SUCCESS) file: // check whether the response code is 250 Return FALSE; File: // format and send the RCPT command, and receive and verify the server response code. SEmail = (LPCTSTR) msg-> m_strTo; STo. Format (_ T ("rcpt to: <% s> rn"), (LPCTSTR) sEmail ); M_wsSMTPServer.Send (LPCTSTR) sTo, sTo. GetLength ()); If (! Get_response (GENERIC_SUCCESS) file: // check whether the response code is 250 Return FALSE; File: // format and send the DATA command, and receive and verify the server response code. STemp = _ T ("DATArn "); M_wsSMTPServer.Send (LPCTSTR) sTemp, sTemp. GetLength ()); If (! Get_response (DATA_SUCCESS) file: // check whether the response code is 354 Return FALSE; File: // send the headers formatted according to RFC 822. M_wsSMTPServer.Send (LPCTSTR) msg-> m_strHeader, msg-> m_strHeader.GetLength ()); ...... File: // send the email body formatted according to RFC 822. STemp = msg-> m_strBody; If (sTemp. Left (3) = _ T (". rn ")) STemp = _ T (".") + sTemp; While (nPos = sTemp. Find (szBad)>-1) { SCooked = sTemp. Mid (nStart, nPos ); SCooked + = szGood; STemp = sCooked + sTemp. Right (sTemp. GetLength ()-(nPos + nBadLength )); } M_wsSMTPServer.Send (LPCTSTR) sTemp, sTemp. GetLength ()); File: // end mark of the sent content data "<CRLF>. <CRLF>", and check the response code returned. STemp = _ T ("rn. rn "); M_wsSMTPServer.Send (LPCTSTR) sTemp, sTemp. GetLength ()); If (! Get_response (GENERIC_SUCCESS) // check whether the response code is 250 Return FALSE; |
By now, the session process of the SMTP protocol has basically been reflected in the program, based on the network communication capability provided by socket sockets, the communication and interaction process based on SMTP commands and SMTP response codes is realized, so as to send emails through SMTP protocol.
Conclusion
As an application software on the Internet, the design and development of email software must comply with mature technical specifications on the Internet (such as RFC document series) and related protocols (such as pop, SMTP, IMAP, and LDAP ). Only by programming based on the above specifications and protocols can the openness and standardization of mail software products and services be realized. This article focuses on the SMTP protocol and Its Application in VC ++ programming, and provides an open and Standard Program Design for sending emails according to the SMTP protocol. The program described in this article is compiled by Microsoft Visual C ++ 6.0 under Windows 98.