Home >php教程 >PHP开发 >Send email using Socket (php)

Send email using Socket (php)

高洛峰
高洛峰Original
2016-12-02 10:12:151180browse

Introduction to Socket Programming
I would like to state to everyone that I am not a TCP/IP programming expert, so I am just sharing my understanding and experience here.

Use the fsockopen function to open an Internet connection. The function syntax format is:

int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]);

I don’t think I need to explain the meaning of the parameters. Yes, since the SMTP protocol is used here, the port number is 25. After the connection is successfully opened, a socket handle will be returned, which can be used like a file handle. The operations that can be used include fputs(), fgets(), feof(), fclose()
, etc.

 That’s it for a very simple introduction.

The basis of SMTP

The general command format of the Internet protocol based on TCP/IP is implemented through the request/response method, and all text information is used, so it is easier to process. SMTP is the abbreviation of Simple Mail Transfer Protocol, which enables the client to send emails to the server. So
The command mentioned below refers to the client sending a request instruction to the server, and the response refers to the information returned by the server to the client.

 SMTP is divided into two parts: command header and message body. The command header mainly completes the connection between the client and the server, verification, etc. The whole process consists of multiple commands. After each command is sent to the server, the server will give response information, usually a 3-digit response code and response text. The response codes returned by different servers comply with the protocol, but the response text does not. There is a carriage return character at the end of each command and response, so that commands and responses can be processed using fputs() and fgets(). SMTP command and response messages are single lines. The message body is the body of the email

, and the final closing line should be a separate "." as the closing line.


Some commonly used SMTP commands on the client are:

HELO hostname: greet the server and inform the client of the machine name used. You can fill it in casually
MAIL FROM: sender_id: tell the server the address of the sender

RCPT TO: receiver_id: tell The address of the recipient of the server

DATA: The content of the letter begins to be transmitted below, and it must end with a special line containing only .

RESET: Cancel the previous command and start over

VERIFY userid: Verify whether the account exists (this command is optional) command, the server may not support it)
QUIT: Exit the connection, end
The response information returned by the server is (format: response code + space + explanation):

220 Service ready (this information will be returned when the socket connection is successful)
221 is being processed
250 The request email action is correct and completed (this information will be returned if the HELO, MAIL FROM, RCPT TO, QUIT command is executed successfully)
354 Start sending data and ends with. (This information will be returned if the DATA command is executed successfully. Customer The terminal should send information)

500 Syntax error, command cannot be recognized

550 Command cannot be executed, email is invalid
552 Interrupt processing: The user exceeds the file space
A simple command header is given below (this is done after opening the socket), This is the test result of my sending an email to stmp.263.net:

HELO limodou
250 smtp.263.net
MAIL FROM: chatme@263.net
250 Ok

RCPT TO: chatme@263.net

250 Ok
DATA
354 End data with .

This is some simple knowledge of SMTP. Related content can be found in RFC.

RFC 821 defines related commands for receiving/sending emails.
RFC 822 specifies email?
RFC 2045-2048 specifies multimedia email?
RFC 1113, 1422-1424 discusses how to improve the confidentiality of email.

Implementation of send_mail class
Now I will introduce the send mail class I wrote. With the above preparatory knowledge, the following is the implementation.

Member variables of the class

var $lastmessage; //Record the last response message returned

var $lastact; //The last action, in string form

var $welcome; //Used behind HELO to welcome users

var $debug; //Whether to display debugging information
var $smtp; //smtp server
var $port; //smtp port number
var $fp; //socket handle

  Among them, $lastmessage and $lastact are used to record the last A response message and executed command, which the user can use when an error occurs
. For testing needs, I also defined the $debug variable. When its value is true, some execution information will be displayed during the running process, otherwise there will be no output. $fp is used to save the opened socket handle.

Construction of class


------------------------------------------------ --------------------------------
function send_mail($smtp, $welcome="", $debug=false)
{
if(empty($smtp)) die("SMTP cannt be NULL!");
$this->smtp=$smtp;
if(empty($welcome))
{
$this-> welcome=gethostbyaddr("localhost");
}
else
$this->welcome=$welcome;
$this->debug=$debug;
$this->lastmessage="";
$this- >lastact="";
$this->port="25";
}
---------------------------- -------------------------------------------------- --
 This constructor mainly completes the determination and setting of some initial values. $welcome is used in the HELO directive to tell the server the user's name.
The HELO command requires a machine name, but it can be used without it. If the user does not provide $welcome, the local machine name is automatically searched.

Show debugging information

--------------------------------------------- -------------------------------------
1 function show_debug($message, $inout)
2 {
3 if ($this->debug)
4 {
5 if($inout=="in") //Response information
6 {
7 $m='<< ';
8 }
9 else
10 $m='>> ';
11 if(!ereg("n$", $message))
12 $message .= "
";
13 $message=nl2br( $message);
14 echo "${m}${message}";
15 }
16 }
------------ -------------------------------------------------- ------------------
 This function is used to display debugging information. You can specify in $inout whether it is an upload instruction or a returned response. If it is an upload instruction, use "out"; if it is a returned response, use "in".

Line 3 determines whether to output debugging information.

In line 5, determine whether it is a response message. If so, add "<<" in front of the information in line 7 to distinguish the information; otherwise, add ">>" in line 10 to distinguish it. Upload instructions.
Line 11-12, determine whether the last line of the information string is a newline character, if not, add an HTML newline mark. Line 13 converts all newline characters into HTML
   newline tags.
Line 14, output the entire message, and set the color of the message to gray to show the difference.

Execute a command

--------------------------------------------- -----------------------------------------------

1 function do_command($command, $code)
2 {
3 $this->lastact=$command;
4 $this->show_debug($this->lastact, "out");
5 fputs ( $this->fp, $this-> ;lafact );
6 $this->lastmessage = fgets ( $this->fp, 512 );
7 $this->show_debug($this->lastmessage, "in");
8 if( !ereg("^$code", $this->lastmessage))
9 {
10 return false;
11 }
12 else
13 return true;
14 }
---------- -------------------------------------------------- --------------------
When writing the socket processing part, I found that the processing of some commands is very similar, such as HELO, MAIL FROM, RCPT TO, QUIT, DATA commands,
Both require that the relevant content be displayed based on whether the debugging information is displayed. At the same time, for the returned response code, if it is expected, the processing should continue.
If it is not expected, the processing should be interrupted. Therefore, for the sake of clarity and simplification, a general processing function is specially written for processing these commands.
$code in the parameters of the function is the expected response code. If the response code is the same, it means the processing is successful, otherwise an error occurs.

Line 3 records the last executed command.

Line 4 displays the upload command.

Line 5 uses fputs to actually transfer instructions to the server.
Line 6, the response information received from the server will be placed in the last response message variable.
Line 7 displays the response information.
Line 8 determines whether the response information is expected. If so, line 13 returns success (true), otherwise line 10 returns failure (false).

In this way, on the one hand, this function completes the function of sending and displaying instructions and information, and on the other hand, it judges whether the returned response is successful.

Email sending processing

 The following is the real secret, but you have to look carefully. :)

-------------------------------------------------------------------------------- 
1 function send( $to,$from,$subject,$message) 
2 { 

4 //连接服务器 
5 $this->lastact="connect"; 

7 $this->show_debug("Connect to SMTP server : ".$this->smtp, "out"); 
8 $this->fp = fsockopen ( $this->smtp, $this->port ); 
9 if ( $this->fp ) 
10 { 
11 
12 set_socket_blocking( $this->fp, true ); 
13 $this->lastmessage=fgets($this->fp,512); 
14 $this->show_debug($this->lastmessage, "in"); 
15 
16 if (! ereg ( "^220", $this->lastmessage ) ) 
17 { 
18 return false; 
19 } 
20 else 
21 { 
22 $this->lastact="HELO " . $this->welcome . "n"; 
23 if(!$this->do_command($this->lastact, "250")) 
24 { 
25 fclose($this->fp); 
26 return false; 
27 } 
28 
29 $this->lastact="MAIL FROM: $from" . "n"; 
30 if(!$this->do_command($this->lastact, "250")) 
31 { 
32 fclose($this->fp); 
33 return false; 
34 } 
35 
36 $this->lastact="RCPT TO: $to" . "n"; 
37 if(!$this->do_command($this->lastact, "250")) 
38 { 
39 fclose($this->fp); 
40 return false; 
41 } 
42 
43 //发送正文 
44 $this->lastact="DATAn"; 
45 if(!$this->do_command($this->lastact, "354")) 
46 { 
47 fclose($this->fp); 
48 return false; 
49 } 
50 
51 //处理Subject头 
52 $head="Subject: $subjectn"; 
53 if(!empty($subject) && !ereg($head, $message)) 
54 { 
55 $message = $head.$message; 
56 } 
57 
58 //处理From头 
59 $head="From: $fromn"; 
60 if(!empty($from) && !ereg($head, $message)) 
61 { 
62 $message = $head.$message; 
63 } 
64 
65 //处理To头 
66 $head="To: $ton"; 
67 if(!empty($to) && !ereg($head, $message)) 
68 { 
69 $message = $head.$message; 
70 } 
71 
72 //加上结束串 
73 if(!ereg("n.n", $message)) 
74 $message .= "n.n"; 
75 $this->show_debug($message, "out"); 
76 fputs($this->fp, $message); 
77 
78 $this->lastact="QUITn"; 
79 if(!$this->do_command($this->lastact, "250")) 
80 { 
81 fclose($this->fp); 
82 return false; 
83 } 
84 } 
85 return true; 
86 } 
87 else 
88 { 
89 $this->show_debug("Connect failed!", "in"); 
90 return false; 
91 } 
92 } 
-------------------------------------------------------------------------------- 
  有些意思很清楚的我就不说了。

  这个函数一共有四个参数,分别是$to表示收信人,$from表示发信人,$subject表求邮件主题和$message 
表示邮件体。如果处理成功则返回true,失败则返回false。

Line 8, connect to the mail server, if successful the response code should be 220.
Line 12 sets the blocking mode, indicating that the information must be returned before continuing. See the manual for detailed instructions.
Line 16, determine whether the response code is 220, if so, continue processing, otherwise an error will be returned.
Line 22-27, processing the HELO instruction, the expected response code is 250.
Line 29-34, processing the MAIL FROM instruction, the expected response code is 250.
Line 36-41, processing the RCPT TO instruction, the expected response code is 250.
Line 44-49, processing the DATA command, the expected response code is 354.
Line 51-76, generate the email body and send it.
Lines 52-56, if $subject is not empty, check whether there is a subject part in the email body. If not, add the subject part.
Lines 59-63, if $from is not empty, check whether there is a sender part in the email body. If not, add the sender part.
Lines 66-70, if $to is not empty, check whether there is a recipient part in the email body. If not, add the recipient part.
Lines 73-74, check whether the email body has an ending line, and if not, add the ending line of the email body (with "." as a special line as a separate line).
Line 76, send the email body.
Line 78-83, execute QUIT to terminate the connection with the server, the expected response code is 250.
Line 85, returns the processing success flag (true).
Lines 81-91, processing of failed connection to the server.

 The above is the implementation of the entire send_mail class, which should not be difficult. An example is given below.

Email Sending Example
Let’s give the simplest example first:
---------------------------------- --------------------------------------------------
1 include "sendmail.class.php3";
2 $email="Hello, this is a test letter!";
3 $sendmail=new send_mail("smtp.263.net", "limodou", true); //Display the adjustment information
4 if($sendmail->send("chatme@263.net", "chatme@263.net", "test", $email))
5 {
6 echo "Send successfully !
";
7 }
8 else
9 {
10 echo "Sending failed!
";
11 }
?>
------------- -------------------------------------------------- ------------------
Line 1, load the send_mail class.
Line 3, create an instance of the class and set the display information. If you don’t want to display it, you can
  $sendmail=new send_mail("smtp.263.net");.
Line 4, send email.


It’s simple, isn’t it? Next, we will give an example of sending an HTML attachment based on the previous example of sending a MIME email.

------------------------------------------------ --------------------------------

include "MIME.class.php3";
/ /Note, in the article about sending MIME emails, the name of this class file is MIME.class. Here I changed it to something like this

$to = 'chatme@263.net'; //Changed to the recipient's email
$ str = "Newsletter for ".date('M Y', time());

//The information was changed by me
$html_data = ''. $str . '

Hello! This is a test!

';

// Generate MIME class instance
$mime = new MIME_mail("chatme@263.net", $to, $str);

//Add HTML attachment
$mime->attach($html_data, "", HTML, BASE64 );

//Comment out and use my sending email processing
//$mime->send_mail();

//Generate email
$mime->gen_email();

//Display email information
//echo $mime->email."
";

//Include sendmail file
include "sendmail.class.php3";

//Create instance
$sendmail=new send_mail("smtp .263.net", "limodou", true);

//Send mail
$sendmail->send("chatme@263.net", "chatme@263.net", $str, $mime-> ;email);

?>


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn