您好,欢迎访问一九零五行业门户网

php 邮件发送类_PHP教程

php 邮件发送类
class smtp
{
    /**
     *  smtp server port
     *  @var int
     */
    var $smtp_port = 25;
/**
     *  smtp reply line ending
     *  @var string
     */
    var $crlf = rn;
/**
     *  sets whether debugging is turned on
     *  @var bool
     */
    var $do_debug;       # the level of debug to perform
    /**#@+
     * @access private
     */
    var $smtp_conn;      # the socket to the server
    var $error;          # error if any on the last call
    var $helo_rply;      # the reply the server sent to us for helo
    /**#@-*/
    /**
     * initialize the class so that the data is in a known state.
     * @access public
     * @return void
     */
    function smtp() {
        $this->smtp_conn = 0;
        $this->error = null;
        $this->helo_rply = null;
        $this->do_debug = 0;
    }
    /*************************************************************
     *                    connection functions                  *
     ***********************************************************/
    /**
     * connect to the server specified on the port specified.
     * if the port is not specified use the default smtp_port.
     * if tval is specified then a connection will try and be
     * established with the server for that number of seconds.
     * if tval is not specified the default is 30 seconds to
     * try on the connection.
     *
     * smtp code success: 220
     * smtp code failure: 421
     * @access public
     * @return bool
     */
    function connect($host,$port=0,$tval=30) {
        # set the error val to null so there is no confusion
        $this->error = null;
        # make sure we are __not__ connected
        if($this->connected()) {
            # ok we are connected! what should we do?
            # for now we will just give an error saying we
            # are already connected
            $this->error =
                array(error => already connected to a server);
            return false;
        }
        if(empty($port)) {
            $port = $this->smtp_port;
        }
        #connect to the smtp server
        $this->smtp_conn = fsockopen($host,    # the host of the server
                                     $port,    # the port to use
                                     $errno,   # error number if any
                                     $errstr,  # error message if any
                                     $tval);   # give up after ? secs
        # verify we connected properly
        if(empty($this->smtp_conn)) {
            $this->error = array(error => failed to connect to server,
                                 errno => $errno,
                                 errstr => $errstr);
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : $errstr ($errno) . $this->crlf;
            }
            return false;
        }
        # sometimes the smtp server takes a little longer to respond
        # so we will give it a longer timeout for the first read
        // windows still does not have support for this timeout function
        if(substr(php_os, 0, 3) != win)
           socket_set_timeout($this->smtp_conn, $tval, 0);
        # get any announcement stuff
        $announce = $this->get_lines();
        # set the timeout  of any socket functions at 1/10 of a second
        //if(function_exists(socket_set_timeout))
        //   socket_set_timeout($this->smtp_conn, 0, 100000);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $announce;
        }
        return true;
    }
    /**
     * performs smtp authentication.  must be run after running the
     * hello() method.  returns true if successfully authenticated.
     * @access public
     * @return bool
     */
    function authenticate($username, $password) {
        // start authentication
        fputs($this->smtp_conn,auth login . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($code != 334) {
            $this->error =
                array(error => auth not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        // send encoded username
        fputs($this->smtp_conn, base64_encode($username) . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($code != 334) {
            $this->error =
                array(error => username not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        // send encoded password
        fputs($this->smtp_conn, base64_encode($password) . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($code != 235) {
            $this->error =
                array(error => password not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * returns true if connected to a server otherwise false
     * @access private
     * @return bool
     */
    function connected() {
        if(!empty($this->smtp_conn)) {
            $sock_status = socket_get_status($this->smtp_conn);
            if($sock_status[eof]) {
                # hmm this is an odd situation... the socket is
                # valid but we aren't connected anymore
                if($this->do_debug >= 1) {
                    echo smtp -> notice: . $this->crlf .
                         eof caught while checking if connected;
                }
                $this->close();
                return false;
            }
            return true; # everything looks good
        }
        return false;
    }
    /**
     * closes the socket and cleans up the state of the class.
     * it is not considered good to use this function without
     * first trying to use quit.
     * @access public
     * @return void
     */
    function close() {
        $this->error = null; # so there is no confusion
        $this->helo_rply = null;
        if(!empty($this->smtp_conn)) {
            # close the connection and cleanup
            fclose($this->smtp_conn);
            $this->smtp_conn = 0;
        }
    }
/***************************************************************
     *                        smtp commands                       *
     *************************************************************/
    /**
     * issues a data command and sends the msg_data to the server
     * finializing the mail transaction. $msg_data is the message
     * that is to be send with the headers. each header needs to be
     * on a single line followed by a with the message headers
     * and the message body being seperated by and additional .
     *
     * implements rfc 821: data
     *
     * smtp code intermediate: 354
     *     [data]
     *     .
     *     smtp code success: 250
     *     smtp code failure: 552,554,451,452
     * smtp code failure: 451,554
     * smtp code error  : 500,501,503,421
     * @access public
     * @return bool
     */
    function data($msg_data) {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called data() without being connected);
            return false;
        }
        fputs($this->smtp_conn,data . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 354) {
            $this->error =
                array(error => data command not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        # the server is ready to accept data!
        # according to rfc 821 we should not send more than 1000
        # including the crlf
        # characters on a single line so we will break the data up
        # into lines by r and/or n then if needed we will break
        # each of those into smaller lines to fit within the limit.
        # in addition we will be looking for lines that start with
        # a period '.' and append and additional period '.' to that
        # line. note: this does not count towards are limit.
        # normalize the line breaks so we know the explode works
        $msg_data = str_replace(rn,n,$msg_data);
        $msg_data = str_replace(r,n,$msg_data);
        $lines = explode(n,$msg_data);
        # we need to find a good way to determine is headers are
        # in the msg_data or if it is a straight msg body
        # currently i'm assuming rfc 822 definitions of msg headers
        # and if the first field of the first line (':' sperated)
        # does not contain a space then it _should_ be a header
        # and we can process all lines before a blank line as
        # headers.
        $field = substr($lines[0],0,strpos($lines[0],:));
        $in_headers = false;
        if(!empty($field) && !strstr($field, )) {
            $in_headers = true;
        }
        $max_line_length = 998; # used below; set here for ease in change
        while(list(,$line) = @each($lines)) {
            $lines_out = null;
            if($line == && $in_headers) {
                $in_headers = false;
            }
            # ok we need to break this line up into several
            # smaller lines
            while(strlen($line) > $max_line_length) {
                $pos = strrpos(substr($line,0,$max_line_length), );
                $lines_out[] = substr($line,0,$pos);
                $line = substr($line,$pos + 1);
                # if we are processing headers we need to
                # add a lwsp-char to the front of the new line
                # rfc 822 on long msg headers
                if($in_headers) {
                    $line = t . $line;
                }
            }
            $lines_out[] = $line;
            # now send the lines to the server
            while(list(,$line_out) = @each($lines_out)) {
                if(strlen($line_out) > 0)
                {
                    if(substr($line_out, 0, 1) == .) {
                        $line_out = . . $line_out;
                    }
                }
                fputs($this->smtp_conn,$line_out . $this->crlf);
            }
        }
        # ok all the message data has been sent so lets get this
        # over with aleady
        fputs($this->smtp_conn, $this->crlf . . . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => data not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * expand takes the name and asks the server to list all the
     * people who are members of the _list_. expand will return
     * back and array of the result or false if an error occurs.
     * each value in the array returned has the format of:
     *     [ ]
     * the definition of is defined in rfc 821
     *
     * implements rfc 821: expn
     *
     * smtp code success: 250
     * smtp code failure: 550
     * smtp code error  : 500,501,502,504,421
     * @access public
     * @return string array
     */
    function expand($name) {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called expand() without being connected);
            return false;
        }
        fputs($this->smtp_conn,expn . $name . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => expn not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        # parse the reply and place in our array to return to user
        $entries = explode($this->crlf,$rply);
        while(list(,$l) = @each($entries)) {
            $list[] = substr($l,4);
        }
        return $list;
    }
    /**
     * sends the helo command to the smtp server.
     * this makes sure that we and the server are in
     * the same known state.
     *
     * implements from rfc 821: helo
     *
     * smtp code success: 250
     * smtp code error  : 500, 501, 504, 421
     * @access public
     * @return bool
     */
    function hello($host=) {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called hello() without being connected);
            return false;
        }
        # if a hostname for the helo wasn't specified determine
        # a suitable one to send
        if(empty($host)) {
            # we need to determine some sort of appopiate default
            # to send to the server
            $host = localhost;
        }
        // send extended hello first (rfc 2821)
        if(!$this->sendhello(ehlo, $host))
        {
            if(!$this->sendhello(helo, $host))
                return false;
        }
        return true;
    }
    /**
     * sends a helo/ehlo command.
     * @access private
     * @return bool
     */
    function sendhello($hello, $host) {
        fputs($this->smtp_conn, $hello . . $host . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => $hello . not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        $this->helo_rply = $rply;
return true;
    }
    /**
     * gets help information on the keyword specified. if the keyword
     * is not specified then returns generic help, ussually contianing
     * a list of keywords that help is available on. this function
     * returns the results back to the user. it is up to the user to
     * handle the returned data. if an error occurs then false is
     * returned with $this->error set appropiately.
     *
     * implements rfc 821: help [ ]
     *
     * smtp code success: 211,214
     * smtp code error  : 500,501,502,504,421
     * @access public
     * @return string
     */
    function help($keyword=) {
        $this->error = null; # to avoid confusion
        if(!$this->connected()) {
            $this->error = array(
                    error => called help() without being connected);
            return false;
        }
        $extra = ;
        if(!empty($keyword)) {
            $extra = . $keyword;
        }
        fputs($this->smtp_conn,help . $extra . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 211 && $code != 214) {
            $this->error =
                array(error => help not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return $rply;
    }
    /**
     * starts a mail transaction from the email address specified in
     * $from. returns true if successful or false otherwise. if true
     * the mail transaction is started and then one or more recipient
     * commands may be called followed by a data command.
     *
     * implements rfc 821: mail from:
     *
     * smtp code success: 250
     * smtp code success: 552,451,452
     * smtp code success: 500,501,421
     * @access public
     * @return bool
     */
    function mail($from) {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called mail() without being connected);
return false;
        }
        fputs($this->smtp_conn,mail from: . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => mail not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * sends the command noop to the smtp server.
     *
     * implements from rfc 821: noop
     *
     * smtp code success: 250
     * smtp code error  : 500, 421
     * @access public
     * @return bool
     */
    function noop() {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called noop() without being connected);
            return false;
        }
        fputs($this->smtp_conn,noop . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => noop not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * sends the quit command to the server and then closes the socket
     * if there is no error or the $close_on_error argument is true.
     *
     * implements from rfc 821: quit
     *
     * smtp code success: 221
     * smtp code error  : 500
     * @access public
     * @return bool
     */
    function quit($close_on_error=true) {
        $this->error = null; # so there is no confusion
        if(!$this->connected()) {
            $this->error = array(
                    error => called quit() without being connected);
            return false;
        }
        # send the quit command to the server
        fputs($this->smtp_conn,quit . $this->crlf);
        # get any good-bye messages
        $byemsg = $this->get_lines();
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $byemsg;
        }
        $rval = true;
        $e = null;
        $code = substr($byemsg,0,3);
        if($code != 221) {
            # use e as a tmp var cause close will overwrite $this->error
            $e = array(error => smtp server rejected quit command,
                       smtp_code => $code,
                       smtp_rply => substr($byemsg,4));
            $rval = false;
            if($this->do_debug >= 1) {
                echo smtp -> error: . $e[error] . : .
                         $byemsg . $this->crlf;
            }
        }
        if(empty($e) || $close_on_error) {
            $this->close();
        }
        return $rval;
    }
    /**
     * sends the command rcpt to the smtp server with the to: argument of $to.
     * returns true if the recipient was accepted false if it was rejected.
     *
     * implements from rfc 821: rcpt to:
     *
     * smtp code success: 250,251
     * smtp code failure: 550,551,552,553,450,451,452
     * smtp code error  : 500,501,503,421
     * @access public
     * @return bool
     */
    function recipient($to) {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called recipient() without being connected);
            return false;
        }
        fputs($this->smtp_conn,rcpt to: . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250 && $code != 251) {
            $this->error =
                array(error => rcpt not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * sends the rset command to abort and transaction that is
     * currently in progress. returns true if successful false
     * otherwise.
     *
     * implements rfc 821: rset
     *
     * smtp code success: 250
     * smtp code error  : 500,501,504,421
     * @access public
     * @return bool
     */
    function reset() {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called reset() without being connected);
            return false;
        }
        fputs($this->smtp_conn,rset . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => rset failed,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * starts a mail transaction from the email address specified in
     * $from. returns true if successful or false otherwise. if true
     * the mail transaction is started and then one or more recipient
     * commands may be called followed by a data command. this command
     * will send the message to the users terminal if they are logged
     * in.
     *
     * implements rfc 821: send from:
     *
     * smtp code success: 250
     * smtp code success: 552,451,452
     * smtp code success: 500,501,502,421
     * @access public
     * @return bool
     */
    function send($from) {
        $this->error = null; # so no confusion is caused
        if(!$this->connected()) {
            $this->error = array(
                    error => called send() without being connected);
            return false;
        }
        fputs($this->smtp_conn,send from: . $from . $this->crlf);
        $rply = $this->get_lines();
        $code = substr($rply,0,3);
        if($this->do_debug >= 2) {
            echo smtp -> from server: . $this->crlf . $rply;
        }
        if($code != 250) {
            $this->error =
                array(error => send not accepted from server,
                      smtp_code => $code,
                      smtp_msg => substr($rply,4));
            if($this->do_debug >= 1) {
                echo smtp -> error: . $this->error[error] .
                         : . $rply . $this->crlf;
            }
            return false;
        }
        return true;
    }
    /**
     * starts a mail transaction from the email address specified in
     * $from. returns true if successful or false otherwise. if true
     * the mail transaction is started and then one or more recipient
     * commands may be called followed by a data command. this command
     * will send the message to the users terminal if they are logged
     * in and send them an email.
     *
     * implements rfc 821: saml from:
     *
     * smtp code success: 250
     * smtp code success: 552,451,452
     * smtp code success: 500,501,502,421
     * @access public
     * @return bool
  &nbs
其它类似信息

推荐信息