Send email with socket in PHP

Source: Internet
Author: User
Tags empty ereg execution final header connect net socket
Of the several PHP home pages that the author is applying for, there is not much that can be done to provide mail functionality, and there is no context after the mail () function is always called. But e-mail plays an increasingly important role in online life. Think of the net worm online not to receive mail can call the real net worm? The role of mail I don't want to talk about it, but what if home space doesn't support mail ()? I also think through the socket to achieve mail delivery, but helpless to use PHP socket programming is not familiar with, plus send mail to use the SMTP protocol, but also read a lot of English, so has not been studied. Finally one day I found an article about using socket programming to send mail. I unlike it as a copy and transformed it into a PHP-usable class for everyone to use. The original article is just a simple example, and there are some mistakes, after many experiments, the transformation has finally changed it to a direct use of the socket, to the designated mailbox to send mail class, if you and the previous article on the sending of MIME combined, you can implement in the Mail () function to send mail on the Web site. Because the process of sending a message takes time, it may not be the same as the mail () processing mechanism, so the speed is slower, but can solve the need to send the mail function of the urgent, but you can also learn to use PHP for socket programming. Here is the implementation of this class introduction to everyone, while explaining some of the basic knowledge of SMTP.

Introduction to Socket Programming
To all of you, I am not a TCP/IP programming experts, so here is only to tell me a little understanding and experience.

Use the Fsockopen function to open an Internet connection, function syntax format:

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

The meaning of the parameter I don't want to talk about it. Because you want to use the SMTP protocol, the port number is 25. After the connection is opened successfully, it returns a
Socket handle, which can be used just like a file handle. Available operations are fputs (), fgets (), feof (), fclose ()
Wait

It's very simple to introduce it here.

The basics of SMTP
TCP/IP based Internet Protocol General Command format is implemented through the request/Response mode, using the text information, so it is easier to deal with. SMTP is the abbreviation for Simple Mail Transfer Protocol, which enables clients to send mail to the server. So the command described below means that the client sends a request to the server, and the response refers to the information that the server returns to the client.

SMTP is divided into two parts, the command header and the information body. The command header completes the client-server connection, authentication, and so on. The whole process consists of several commands. After each command is sent to the server, the response information is given by the server, typically a 3-digit response code and response text. The response code returned by the different servers is compliant, but the response body is not necessary. There is a carriage return at the end of each command and response, so that fputs () and fgets () can be used to process commands and responses. The command and response information for SMTP is a single line. The body is the body part of the message, and the final end line should be a separate "." As the end line.

Some common SMTP directives for clients are:

HELO hostname: Say hello to the server and tell the client the name of the machine, you can fill it out casually.
MAIL from:sender_id: Tell the server the sender's address
RCPT to:receiver_id: Tell the server the address of the addressee
DATA: Starts with the transmission of the letter and ends with a special line containing only.
RESET: Cancel the instructions just now and start anew
VERIFY UserID: Verify the existence of the account number (this instruction is optional, the server may not support)
QUIT: Exit connection, end
The response information returned by the server is (in the format: Response code + SPACE + explanation):

220 The service is ready (this information is returned when the socket connection succeeds)
221 being processed
250 The Request mail action is correct, completes (helo,mail from,rcpt to,quit instruction execution Success will return this information)
354 Start sending data, end with. (The data instruction succeeds returns this information, the client should send the information)
500 syntax error, command not recognized
550 command cannot be executed, invalid mailbox
552 Interrupt Processing: User exceeds file space
The following is a simple command header (which is done after opening the socket) and is the test result of my email to stmp.263.net:

HELO Limodou
Smtp.263.net
MAIL from: chatme@263.net
Ok
RCPT to: chatme@263.net
Ok
DATA
354 end data with.
To: chatme@263.net
From: chatme@263.net
Subject:test
From: chatme@263.net
Test
.
QUIT
Ok:queued as C46411c5097e0

This is the simple knowledge of some SMTP. Relevant content can be consulted in the RFC.

RFC 821 defines the instructions for receiving/sending e-mail.
RFC 822 Formats the contents of the message.
RFC 2045-2048 has a format for multimedia mail content,
RFC 1113, 1422-1424 discusses how to improve the confidentiality of e-mail messages.

Implementation of Send_mail Class
Now I'm going to start by introducing the Send mail Class I wrote. With the above preparatory knowledge, the following is achieved.

class's member variable

var $lastmessage; Record the last response information returned
var $lastact; The last action, the string form
var $welcome; Used behind the helo, welcome to the user
var $debug; Whether to display debug information
var $smtp; SMTP server
var $port; SMTP port number
var $fp; Socket handle

Where $lastmessage and $lastact are used to record the last response information and the commands that are executed, and when an error occurs, the user can use them. For testing purposes, I also defined the $DEBUG variable, which displays some execution information when the value is true, otherwise there is no output. $FP is used to save the open socket handle.

The construction of a 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 used in helo instructions, tell the server user's name. The HELO directive requires a machine name, but it is not necessary either. If the user does not give a $welcome, the local machine name is automatically found.

Display 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
$m = ' >> ';
One if (!ereg ("\n$", $message))
$message. = "<br>";
$message =nl2br ($message);
echo "<font color= #999999 >${m}${message}</font>";
15}
16}
--------------------------------------------------------------------------------
This function is used to display debugging information. You can specify whether to upload an instruction or return a response in $inout, use "out" if it is an upload instruction, or use "in" for the returned response.

Line 3rd, to determine if you want to output debug information.
Line 5th, to determine whether the response information, if it is, the 7th line of information before the "<<" to distinguish the information, otherwise in the 10th row plus ">>" to distinguish between the upload instructions.
第11-12 the line to determine if the message string is the last line break, and if not, add the HTML line-wrapping tag. Line 13th lines so that the line break is translated into an HTML newline tag.
Line 14th, the whole piece of information is printed, and the information color is grayed out to make 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-&GT;FP, 512);
7 $this->show_debug ($this->lastmessage, "in");
8 if (!ereg ("^ $code", $this->lastmessage))
9 {
return false;
11}
Or else
return true;
14}
--------------------------------------------------------------------------------
In the Writing socket Processing section found that some of the processing of the command is very similar, such as Helo,mail from,rcpt to,quit,data command, are required to display the debugging information based on whether the relevant content display, and the return response code, if it is expected, should continue processing, If it is not expected, the rationale should be interrupted. So for clarity and simplification, a common processing function is written specifically for the processing of these commands. $code is the expected response code in the parameter of the function, and if the response code is the same, the processing succeeds or an error occurs.

Line 3rd, record the final execution command.
Line 4th, display the upload command.
Line 5th, use fputs to actually transfer instructions to the server.
Line 6th, receiving response information from the server is placed in the last response message variable.
The 7th line shows the response information.
Line 8th, to determine if the response information is expected, and if so, the 13th row returns success (true), otherwise it fails on line 10th (false).

This function, on the one hand, completes the display function of instruction and information, and does not judge the success of the return response.

Mail delivery processing

Here is the real secret, but look carefully. :)

--------------------------------------------------------------------------------
1 function Send ($to, $from, $subject, $message)
2 {
3
4//Connection server
5 $this->lastact= "Connect";
6
7 $this->show_debug ("Connect to SMTP Server:". $this->smtp, "out");
8 $this-&GT;FP = Fsockopen ($this->smtp, $this->port);
9 if ($this-&GT;FP)
10 {
11
Set_socket_blocking ($this-&GT;FP, true);
$this->lastmessage=fgets ($this->fp,512);
$this->show_debug ($this->lastmessage, "in");
15
if (! Ereg ("^220", $this->lastmessage))
17 {
return false;
19}
Else
21 {
$this->lastact= "HELO". $this->welcome. "\ n";
if (! $this->do_command ($this->lastact, "250"))
24 {
Fclose ($this-&GT;FP);
return false;
27}
28
$this->lastact= "MAIL from: $from". "\ n";
if (! $this->do_command ($this->lastact, "250"))
31 {
Fclose ($this-&GT;FP);
return false;
34}
35
$this->lastact= "RCPT to: $to". "\ n";
Panax Notoginseng if (! $this->do_command ($this->lastact, "250"))
38 {
Fclose ($this-&GT;FP);
return false;
41}
42
43//Send Text
$this->lastact= "data\n";
if (! $this->do_command ($this->lastact, "354"))
46 {
Fclose ($this-&GT;FP);
return false;
49}
50
51//Processing subject Head
$head = "Subject: $subject \ n";
if (!empty ($subject) &&!ereg ($head, $message))
54 {
$message = $head. $message;
56}
57
58//Processing from head
$head = "From: $from \ n";
if (!empty ($from) &&!ereg ($head, $message))
61 {
$message = $head. $message;
63}
64
65//Processing to head
$head = "to: $to \ n";
if (!empty ($to) &&!ereg ($head, $message))
68 {
$message = $head. $message;
70}
71
72//Plus end string
if (!ereg ("\n\.\n", $message))
$message. = "\n.\n";
$this->show_debug ($message, "out");
Fputs ($this->fp, $message);
77
$this->lastact= "quit\n";
(! $this->do_command ($this->lastact, "250"))
80 {
Bayi fclose ($this-&GT;FP);
The return false;
83}
84}
return true;
86}
Or else
88 {
$this->show_debug ("Connect failed!", "in");
return false;
91}
92}
--------------------------------------------------------------------------------
Some of the meaning is very clear I will not say.

This function is a total of four parameters, is the $to of the addressee, $from the sender, $subject table for the message subject and $message to represent the message body. Returns true if the processing succeeds, or false if it fails.

Line 8th, connect the mail server if the success response code should be 220.
Line 12th, set blocking mode, indicating that the information must be returned to continue. Read the manual in detail.
Line 16th, to determine whether the response code is 220, if it is, then continue processing, or error return.
第22-27 line, processing helo instruction, expect response code is 250.
第29-34 line, processing the mail from directive, expecting a response code of 250.
第36-41 line, processing rcpt to instruction, the expected response code is 250.
第44-49 line, processing the data instruction, the expected response code is 354.
第51-76 line, generate the message body, and send.
第52-56 line, if $subject is not empty, find out if there is a topic part in the message body, and if not, add the topic section.
第59-63 line, if the $from is not empty, find out if there is a sender part of the message body, if not, add the sender part.
第66-70 line, if the $to is not empty, find out if there is a recipient portion of the message body, and if not, add the recipient portion.
第73-74 the line to find out if the message body has an end line, if not, plus the end line of the message body (with "."). As a special line on a single line).
Line 76th, send the message body.
第78-83 line, perform quit connection to the server and expect a response code of 250.
Line 85th returns the processing Success flag (TRUE).
第81-91 row, processing of failed connections to the server.
The above for the entire Send_mail class implementation, should not be difficult.

An example is given below.

Mail Send instance

First, give the simplest example:
<?php
1 include "sendmail.class.php3";
2 $email = "Hello, this is a test letter!";
3 $sendmail =new send_mail ("Smtp.263.net", "Limodou", true); To display the information for an adjustment
4 if ($sendmail->send ("chatme@263.net", "chatme@263.net"," Test ", $email))
5 {
6 echo "Send success!" <br> ";
7}
8 Else
9 {
Ten echo "Send failed!" <br> ";
11}
?>

Line 1th, load the Send_mail class.
Line 3rd, create an instance of the class, and set the display information, if you do not want to display, you can
$sendmail =new send_mail ("smtp.263.net");.
Line 4th, send the message.


It's simple, isn't it? The previous example of sending a MIME message is given below, giving an example of sending an HTML attachment.

<?php

Include "MIME.CLASS.PHP3";
Note, in the text of a MIME message, this class file is named Mime.class, where I change to this

$to = 'chatme@263.net'; Change to Addressee's mailbox
$str = "Newsletter for". Date (' M Y ', Time ());

I've changed the message.
$html _data = ' <body bgcolor= "#ffffff" >
Hello! This is a test!
</body>

Generate MIME class instances
$mime = new Mime_mail ("chatme@263.net", $to, $STR);

Add HTML attachment
$mime->attach ($html _data, "", HTML, BASE64);

Comment out, using my send mail processing
$mime->send_mail ();

Generate mail
$mime->gen_email ();

Display message Information
echo $mime->email. " <br> ";

Contains sendmail files
Include "SENDMAIL.CLASS.PHP3";

Create an instance
$sendmail =new send_mail ("Smtp.263.net", "Limodou", true);

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

?>
The notes are clearly written so that no more explanations can be made. If in practice, set debug in the Send_mail constructor to false or not to write.




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.