Send emails with Socket Among the several PHP homepage spaces that the author has applied for, there are not many that can provide mail functions. They always have to call the mail() function.
Nothing follows. But email is becoming increasingly important in online life. Think about it, can a real networm be called a networm if you don’t receive emails? mail
I don't want to talk about the role of this, but what if the homepage space does not support mail() sending? I've also thought about implementing emails through sockets
Send, but I was not familiar with socket programming using php. In addition, I have to use the SMTP protocol to send emails, and I have to read a lot of English.
I haven't studied it yet. Finally one day I found an article about sending emails using socket programming. I copied it like a treasure
Bei down and transformed it into a php-available class for everyone to use. The original article is just a simple example, and there is another
After many experiments and transformations, I finally changed it to a class that directly uses socket to send emails to the specified mailbox, such as
If you combine it with the previous article about sending MIME, you can send emails on websites that do not support the mail() function. Because
The process of sending emails takes time, which may not be exactly the same as the processing mechanism of mail(), so the speed is slower, but it can solve the problem of sending.
The urgent need for the email delivery function, and you can also learn to use php to program sockets. The following will introduce the implementation principle of this class to you.
At the same time, I will explain some basic knowledge about SMTP to you.
Introduction to Socket Programming
Let me tell you that I am not a TCP/IP programming expert, so I just expressed my understanding and experience here.
Use the fsocckopen function to open an Internet connection, function syntax format:
int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]);
I don't need to mention the meaning of the parameters. Since we need to use the SMTP protocol, the port number is 25. After the connection is successfully opened, a
Use a socket handle, just like using a file handle. The available operations include fputs(), fgets(), feof(), and fclose()
wait.
This is the very brief introduction.
The basics of SMTP
The general command format of the Internet protocol based on TCP/IP is implemented through request/reply, and all use text information, so
It's easier to handle. SMTP is the abbreviation of the simple mail transmission protocol, which can realize the function of a client sending mail to a server. so
The commands mentioned below refer to the client to issue 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 information body. The command header mainly completes the connection between the client and the server, verification, etc. The whole process consists of multiple lives
Order to form. After each command is sent to the server, the server will give the response information, which is generally a 3-digit response code and response text. Different servers
The response code returned by the server complies with the protocol, but the response body text does not need to be. Each command and response has a carriage return character at the end, so that
Use fputs() and fgets() to process commands and responses. The command and response information of SMTP are all single-line. The information body is email
The final ending line should be ended with a separate "."
Some commonly used SMTP instructions on the client are:
HELO hostname: Say hello to the server and tell the client the name of the machine used, you can fill it in as you like
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 following starts the transmission of the letter content and ends with a special line containing only.
RESET: Cancel the command just now and start again
VERIFY userid: Check whether the account exists (this command is an optional command, and 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 is ready (this message will be returned when the socket connection is successful)
221 Processing
250 The request email action is correct and completed (HELO, MAIL FROM, RCPT TO, QUIT instruction execution will return this information)
354 Start sending data and end with . (This information will be returned after successful execution of the DATA instruction, and the client should send the information)
500 Syntax error, command not recognized
550 The command cannot be executed, the mailbox is invalid
552 Interrupt processing: User exceeds file space
Here is a simple command header (this is done after opening the socket), which is the test result of my email to stmp.:
HELO limodou
250 smtp.
MAIL FROM: chatme@
250 Ok
RCPT TO: chatme@
250 Ok
DATA
354 End data with .
To: chatme@
From: chatme@
Subject: test
From: chatme@
test
.
QUIT
250 Ok: queued as C46411C5097E0
This is some simple knowledge of SMTP. For related content, please refer to RFC.
RFC 821 defines the instructions for receiving/sending emails.
RFC 822 formulates the format of email content.
RFC 2045-2048 has formulated the format of multimedia email content.
RFC 1113, 1422-1424 discusses how to improve the confidentiality of emails.
Implementation of send_mail class
Now let’s start introducing the sending email class I wrote. With the above preliminary knowledge, the following is the implementation.
Member variables of the class
var $lastmessage; //Record the last returned response information
var $lastact; //The last action, string form
var $welcome; //Use it behind HELO, 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 response information and the commands executed. When an error occurs, the user can use it.
We. For testing needs, I also defined the $debug variable, when its value is true, some execution information will be displayed during the run, otherwise no
Any output. $fp is used to save the open socket handle.
Class construction
--------------------------------------------------------------------------------
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 user's name.
The HELO instruction requires the machine name, but it is OK if you don't. If the user does not give $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 .= "<br>";
13 $message=nl2br($message);
14 echo "<font color=#999999>${m}${message}</font>";
15 }
16 }
--------------------------------------------------------------------------------
This function is used to display debugging information. You can specify in $inout whether the uploaded command or the returned response. If it is an uploaded command,
Use "out"; if it is the returned response, use "in".
Line 3 determines whether to output debugging information.
Line 5 determines whether it is response information. If so, add "<<" in front of the information in line 7 to distinguish the information; otherwise add "10 line 10 to line 10
">> "To distinguish uploading instructions.
Lines 11-12 determine whether the information string is a newline character at the end. If not, add the HTML newline tag. Line 13 converts the newline character into HTML
newline tag.
Line 14, output the entire piece of information, and set the information color 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->lastact );
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 }
--------------------------------------------------------------------------------
In writing socket processing section, I found that some commands are handled very similarly, such as HELO, MAIL FROM, RCPT TO, QUIT, DATA commands,
All require that the relevant content be displayed based on whether the debugging information is displayed. At the same time, if the returned response code is expected, it should continue to be processed.
If it is not expected, the reason should be interrupted. Therefore, for clarity and simplicity, a general processing function was specially written for the processing of these commands.
The $code in the function parameter is the expected response code. If the response code is the same as it means the processing is successful, otherwise an error occurs.
Line 3 records the last execution command.
Line 4, display the upload command.
On line 5, use fputs to actually transfer instructions to the server.
In line 6, receiving the response information 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 it returns failure (false) on line 10.
In this way, this function completes the sending and display functions of instructions and information on the one hand, and determines whether the response returned is successful.
Email sending processing
The following is the real secret, but you have to look at it carefully. :)
--------------------------------------------------------------------------------
1 function send( $to,$from,$subject,$message)
2 {
3
4 //Connect the server
5 $this->lastact="connect";
6
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 //Send the text
44 $this->lastact="DATA\n";
45 if(!$this->do_command($this->lastact, "354"))
46 {
47 fclose($this->fp);
48 return false;
49 }
50
51 //Processing Subject header
52 $head="Subject: $subject\n";
53 if(!empty($subject) && !ereg($head, $message))
54 {
55 $message = $head.$message;
56 }
57
58 //Processing From headers
59 $head="From: $from\n";
60 if(!empty($from) && !ereg($head, $message))
61 {
62 $message = $head.$message;
63 }
64
65 //Processing To header
66 $head="To: $to\n";
67 if(!empty($to) && !ereg($head, $message))
68 {
69 $message = $head.$message;
70 }
71
72 //Add to the end string
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="QUIT\n";
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 }
--------------------------------------------------------------------------------
I won't say something that is very clear.
There are four parameters in this function, namely $to represents the recipient, $from represents the sender, $subject table to find the email subject and $message
Indicates the mail body. Return true if processing is successful, and false if it fails.
Line 8, connect to the mail server, if successful, the response code should be 220.
Line 12, setting the blocking mode means that the information must be returned to continue. Please read the manual for detailed instructions.
Line 16 determines whether the response code is 220. If so, continue processing, otherwise an error will be returned.
Lines 22-27, the HELO instruction is processed, and the expected response code is 250.
Lines 29-34, processing the MAIL FROM instruction, the expected response code is 250.
Lines 36-41, processing the RCPT TO instruction, the expected response code is 250.
Lines 44-49, processing the DATA instruction, the expected response code is 354.
Lines 51-76, generate the email body and send it.
Lines 52-56, if $subject is not empty, then look for whether there is a topic part in the email body, and if not, then add the topic part.
Lines 59-63, if $from is not empty, then look for whether there is a sender part in the email body. If not, add the sender part.
Lines 66-70, if $to is not empty, then look for whether there is a recipient part in the email body. If not, add the recipient part.
Lines 73-74, find out whether the email body has an end line. If not, add the end line of the email body (with "." as a special line for a separate line).
Line 76, send the email body.
Lines 78-83, execute the connection between the QUIT node and the server, and the expected response code is 250.
Line 85 returns the processing success flag (true).
Lines 81-91, Handling of failed connection with the server.
The above is the implementation of the entire send_mail class, which should not be very difficult. An example is given below.
Email sending example
Let's give the simplest example first:
--------------------------------------------------------------------------------
<?
1 include ".php3";
2 $email="Hello, this is a test letter!";
3 $sendmail=new send_mail("smtp.", "limodou", true); //Show the display information
4 if($sendmail->send("chatme@", "chatme@", "test", $email))
5 {
6 echo "Send successfully!<br>";
7 }
8 else
9 {
10 echo "Send failed!<br>";
11 }
?>
--------------------------------------------------------------------------------
Line 1, load the send_mail class.
Line 3, create an instance of a class and set the display display information. If you do not want to display it, you can
$sendmail=new send_mail("smtp.");。
Line 4, send the email.
Very simple, isn't it? Here is another example of sending MIME emails in the past, and an example of sending HTML attachments.
--------------------------------------------------------------------------------
<?php
include ".php3";
//Note, in the article sending MIME email, this class file name is, here I changed it to this
$to = 'chatme@'; //Change it to the recipient's email address
$str = "Newsletter for ".date('M Y', time());
//I changed the information less
$html_data = '<html><head><title>'. $str. '</title></head>
<body bgcolor="#ffffff">
Hello! This is a test!
</body>
</html>';
//Generate MIME class instance
$mime = new MIME_mail("chatme@", $to, $str);
//Add HTML attachment
$mime->attach($html_data, "", HTML, BASE64);
//Comment out and use my send email to process
//$mime->send_mail();
//Generate email
$mime->gen_email();
//Show email information
//echo $mime->email."<br>";
//Include sendmail file
include ".php3";
//Create an instance
$sendmail=new send_mail("smtp.", "limodou", true);
//Send email
$sendmail->send("chatme@", "chatme@", $str, $mime->email);
?>
--------------------------------------------------------------------------------
The comments are written very clearly, so I won’t explain them any more. If in actual application, please set the debug in the send_mail constructor to
Just false or not write it.