Ignore:
Timestamp:
2011/01/17 14:46:37 (13 years ago)
Author:
Seasoft
Message:

#403(インクルードしているライブラリ群をバージョンアップする)

  • PEAR::Mail 1.2.0
  • PEAR::Net_SMTP 1.4.4
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/version-2_5-dev/data/module/Net/SMTP.php

    r16300 r19942  
    1919// +----------------------------------------------------------------------+ 
    2020// 
    21 // $Id: SMTP.php,v 1.58 2007/03/28 04:53:34 chagenbu Exp $ 
    22  
    23 $include_dir = realpath(dirname( __FILE__)); 
    24 require_once $include_dir . "/../PEAR.php"; 
    25 require_once $include_dir . "/../Net/Socket.php"; 
     21// $Id: SMTP.php 304535 2010-10-20 06:48:06Z jon $ 
     22 
     23require_once 'PEAR.php'; 
     24require_once 'Net/Socket.php'; 
    2625 
    2726/** 
     
    6766 
    6867    /** 
     68     * Use SMTP command pipelining (specified in RFC 2920) if the SMTP 
     69     * server supports it. 
     70     * 
     71     * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(), 
     72     * somlFrom() and samlFrom() do not wait for a response from the 
     73     * SMTP server but return immediately. 
     74     * 
     75     * @var bool 
     76     * @access public 
     77     */ 
     78    var $pipelining = false; 
     79 
     80    /** 
     81     * Number of pipelined commands. 
     82     * @var int 
     83     * @access private 
     84     */ 
     85    var $_pipelined_commands = 0; 
     86 
     87    /** 
    6988     * Should debugging output be enabled? 
    7089     * @var boolean 
     
    7493 
    7594    /** 
     95     * Debug output handler. 
     96     * @var callback 
     97     * @access private 
     98     */ 
     99    var $_debug_handler = null; 
     100 
     101    /** 
    76102     * The socket resource being used to connect to the SMTP server. 
    77103     * @var resource 
     
    93119     */ 
    94120    var $_arguments = array(); 
     121 
     122    /** 
     123     * Stores the SMTP server's greeting string. 
     124     * @var string 
     125     * @access private 
     126     */ 
     127    var $_greeting = null; 
    95128 
    96129    /** 
     
    115148     * @param integer $port       The port to connect to. 
    116149     * @param string  $localhost  The value to give when sending EHLO or HELO. 
     150     * @param boolean $pipeling   Use SMTP command pipelining 
    117151     * 
    118152     * @access  public 
    119153     * @since   1.0 
    120154     */ 
    121     function Net_SMTP($host = null, $port = null, $localhost = null) 
    122     { 
    123         if (isset($host)) $this->host = $host; 
    124         if (isset($port)) $this->port = $port; 
    125         if (isset($localhost)) $this->localhost = $localhost; 
     155    function Net_SMTP($host = null, $port = null, $localhost = null, $pipelining = false) 
     156    { 
     157        if (isset($host)) { 
     158            $this->host = $host; 
     159        } 
     160        if (isset($port)) { 
     161            $this->port = $port; 
     162        } 
     163        if (isset($localhost)) { 
     164            $this->localhost = $localhost; 
     165        } 
     166        $this->pipelining = $pipelining; 
    126167 
    127168        $this->_socket = new Net_Socket(); 
    128169 
    129         /* 
    130          * Include the Auth_SASL package.  If the package is not available, 
    131          * we disable the authentication methods that depend upon it. 
    132          */ 
    133         if ((@include_once '../Auth/SASL.php') === false) { 
     170        /* Include the Auth_SASL package.  If the package is not 
     171         * available, we disable the authentication methods that 
     172         * depend upon it. */ 
     173        if ((@include_once 'Auth/SASL.php') === false) { 
    134174            $pos = array_search('DIGEST-MD5', $this->auth_methods); 
    135175            unset($this->auth_methods[$pos]); 
     
    147187     * @since   1.1.0 
    148188     */ 
    149     function setDebug($debug) 
     189    function setDebug($debug, $handler = null) 
    150190    { 
    151191        $this->_debug = $debug; 
     192        $this->_debug_handler = $handler; 
     193    } 
     194 
     195    /** 
     196     * Write the given debug text to the current debug output handler. 
     197     * 
     198     * @param   string  $message    Debug mesage text. 
     199     * 
     200     * @access  private 
     201     * @since   1.3.3 
     202     */ 
     203    function _debug($message) 
     204    { 
     205        if ($this->_debug) { 
     206            if ($this->_debug_handler) { 
     207                call_user_func_array($this->_debug_handler, 
     208                                     array(&$this, $message)); 
     209            } else { 
     210                echo "DEBUG: $message\n"; 
     211            } 
     212        } 
    152213    } 
    153214 
     
    164225    function _send($data) 
    165226    { 
    166         if ($this->_debug) { 
    167             echo "DEBUG: Send: $data\n"; 
    168         } 
    169  
    170         if (PEAR::isError($error = $this->_socket->write($data))) { 
    171             return PEAR::raiseError('Failed to write to socket: ' . 
    172                                     $error->getMessage()); 
     227        $this->_debug("Send: $data"); 
     228 
     229        $error = $this->_socket->write($data); 
     230        if ($error === false || PEAR::isError($error)) { 
     231            $msg = ($error) ? $error->getMessage() : "unknown error"; 
     232            return PEAR::raiseError("Failed to write to socket: $msg"); 
    173233        } 
    174234 
     
    213273     *                              may be specified as an array of integer 
    214274     *                              values or as a single integer value. 
     275     * @param   bool    $later      Do not parse the response now, but wait 
     276     *                              until the last command in the pipelined 
     277     *                              command group 
    215278     * 
    216279     * @return  mixed   True if the server returned a valid response code or 
     
    222285     * @see     getResponse 
    223286     */ 
    224     function _parseResponse($valid) 
     287    function _parseResponse($valid, $later = false) 
    225288    { 
    226289        $this->_code = -1; 
    227290        $this->_arguments = array(); 
    228291 
    229         while ($line = $this->_socket->readLine()) { 
    230             if ($this->_debug) { 
    231                 echo "DEBUG: Recv: $line\n"; 
    232             } 
    233  
    234             /* If we receive an empty line, the connection has been closed. */ 
    235             if (empty($line)) { 
    236                 $this->disconnect(); 
    237                 return PEAR::raiseError('Connection was unexpectedly closed'); 
    238             } 
    239  
    240             /* Read the code and store the rest in the arguments array. */ 
    241             $code = substr($line, 0, 3); 
    242             $this->_arguments[] = trim(substr($line, 4)); 
    243  
    244             /* Check the syntax of the response code. */ 
    245             if (is_numeric($code)) { 
    246                 $this->_code = (int)$code; 
    247             } else { 
    248                 $this->_code = -1; 
    249                 break; 
    250             } 
    251  
    252             /* If this is not a multiline response, we're done. */ 
    253             if (substr($line, 3, 1) != '-') { 
    254                 break; 
    255             } 
    256         } 
    257  
    258         /* Compare the server's response code with the valid code. */ 
     292        if ($later) { 
     293            $this->_pipelined_commands++; 
     294            return true; 
     295        } 
     296 
     297        for ($i = 0; $i <= $this->_pipelined_commands; $i++) { 
     298            while ($line = $this->_socket->readLine()) { 
     299                $this->_debug("Recv: $line"); 
     300 
     301                /* If we receive an empty line, the connection has been closed. */ 
     302                if (empty($line)) { 
     303                    $this->disconnect(); 
     304                    return PEAR::raiseError('Connection was unexpectedly closed'); 
     305                } 
     306 
     307                /* Read the code and store the rest in the arguments array. */ 
     308                $code = substr($line, 0, 3); 
     309                $this->_arguments[] = trim(substr($line, 4)); 
     310 
     311                /* Check the syntax of the response code. */ 
     312                if (is_numeric($code)) { 
     313                    $this->_code = (int)$code; 
     314                } else { 
     315                    $this->_code = -1; 
     316                    break; 
     317                } 
     318 
     319                /* If this is not a multiline response, we're done. */ 
     320                if (substr($line, 3, 1) != '-') { 
     321                    break; 
     322                } 
     323            } 
     324        } 
     325 
     326        $this->_pipelined_commands = 0; 
     327 
     328        /* Compare the server's response code with the valid code/codes. */ 
    259329        if (is_int($valid) && ($this->_code === $valid)) { 
    260330            return true; 
    261         } 
    262  
    263         /* If we were given an array of valid response codes, check each one. */ 
    264         if (is_array($valid)) { 
    265             foreach ($valid as $valid_code) { 
    266                 if ($this->_code === $valid_code) { 
    267                     return true; 
    268                 } 
    269             } 
     331        } elseif (is_array($valid) && in_array($this->_code, $valid, true)) { 
     332            return true; 
    270333        } 
    271334 
     
    287350    { 
    288351        return array($this->_code, join("\n", $this->_arguments)); 
     352    } 
     353 
     354    /** 
     355     * Return the SMTP server's greeting string. 
     356     * 
     357     * @return  string  A string containing the greeting string, or null if a  
     358     *                  greeting has not been received. 
     359     * 
     360     * @access  public 
     361     * @since   1.3.3 
     362     */ 
     363    function getGreeting() 
     364    { 
     365        return $this->_greeting; 
    289366    } 
    290367 
     
    304381    function connect($timeout = null, $persistent = false) 
    305382    { 
     383        $this->_greeting = null; 
    306384        $result = $this->_socket->connect($this->host, $this->port, 
    307385                                          $persistent, $timeout); 
     
    314392            return $error; 
    315393        } 
     394 
     395        /* Extract and store a copy of the server's greeting string. */ 
     396        list(, $this->_greeting) = $this->getResponse(); 
     397 
    316398        if (PEAR::isError($error = $this->_negotiate())) { 
    317399            return $error; 
     
    385467        } 
    386468 
     469        if (!isset($this->_esmtp['PIPELINING'])) { 
     470            $this->pipelining = false; 
     471        } 
     472 
    387473        return true; 
    388474    } 
     
    418504     * @param string The requested authentication method.  If none is 
    419505     *               specified, the best supported method will be used. 
     506     * @param bool   Flag indicating whether or not TLS should be attempted. 
     507     * @param string An optional authorization identifier.  If specified, this 
     508     *               identifier will be used as the authorization proxy. 
    420509     * 
    421510     * @return mixed Returns a PEAR_Error with an error message on any 
     
    424513     * @since  1.0 
    425514     */ 
    426     function auth($uid, $pwd , $method = '') 
    427     { 
     515    function auth($uid, $pwd , $method = '', $tls = true, $authz = '') 
     516    { 
     517        /* We can only attempt a TLS connection if one has been requested, 
     518         * we're running PHP 5.1.0 or later, have access to the OpenSSL  
     519         * extension, are connected to an SMTP server which supports the  
     520         * STARTTLS extension, and aren't already connected over a secure  
     521         * (SSL) socket connection. */ 
     522        if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') && 
     523            extension_loaded('openssl') && isset($this->_esmtp['STARTTLS']) && 
     524            strncasecmp($this->host, 'ssl://', 6) !== 0) { 
     525            /* Start the TLS connection attempt. */ 
     526            if (PEAR::isError($result = $this->_put('STARTTLS'))) { 
     527                return $result; 
     528            } 
     529            if (PEAR::isError($result = $this->_parseResponse(220))) { 
     530                return $result; 
     531            } 
     532            if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) { 
     533                return $result; 
     534            } elseif ($result !== true) { 
     535                return PEAR::raiseError('STARTTLS failed'); 
     536            } 
     537 
     538            /* Send EHLO again to recieve the AUTH string from the 
     539             * SMTP server. */ 
     540            $this->_negotiate(); 
     541        } 
     542 
    428543        if (empty($this->_esmtp['AUTH'])) { 
    429             if (version_compare(PHP_VERSION, '5.1.0', '>=')) { 
    430                 if (!isset($this->_esmtp['STARTTLS'])) { 
    431                     return PEAR::raiseError('SMTP server does not support authentication'); 
    432                 } 
    433                 if (PEAR::isError($result = $this->_put('STARTTLS'))) { 
    434                     return $result; 
    435                 } 
    436                 if (PEAR::isError($result = $this->_parseResponse(220))) { 
    437                     return $result; 
    438                 } 
    439                 if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) { 
    440                     return $result; 
    441                 } elseif ($result !== true) { 
    442                     return PEAR::raiseError('STARTTLS failed'); 
    443                 } 
    444  
    445                 /* Send EHLO again to recieve the AUTH string from the 
    446                  * SMTP server. */ 
    447                 $this->_negotiate(); 
    448                 if (empty($this->_esmtp['AUTH'])) { 
    449                     return PEAR::raiseError('SMTP server does not support authentication'); 
    450                 } 
    451             } else { 
    452                 return PEAR::raiseError('SMTP server does not support authentication'); 
    453             } 
     544            return PEAR::raiseError('SMTP server does not support authentication'); 
    454545        } 
    455546 
     
    470561        switch ($method) { 
    471562        case 'DIGEST-MD5': 
    472             $result = $this->_authDigest_MD5($uid, $pwd); 
     563            $result = $this->_authDigest_MD5($uid, $pwd, $authz); 
    473564            break; 
    474565 
     
    482573 
    483574        case 'PLAIN': 
    484             $result = $this->_authPlain($uid, $pwd); 
     575            $result = $this->_authPlain($uid, $pwd, $authz); 
    485576            break; 
    486577 
     
    503594     * @param string The userid to authenticate as. 
    504595     * @param string The password to authenticate with. 
     596     * @param string The optional authorization proxy identifier. 
    505597     * 
    506598     * @return mixed Returns a PEAR_Error with an error message on any 
     
    509601     * @since  1.1.0 
    510602     */ 
    511     function _authDigest_MD5($uid, $pwd) 
     603    function _authDigest_MD5($uid, $pwd, $authz = '') 
    512604    { 
    513605        if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { 
     
    539631         * allow subsequent authentication, so we just silently ignore 
    540632         * it. */ 
    541         if (PEAR::isError($error = $this->_put(' '))) { 
     633        if (PEAR::isError($error = $this->_put(''))) { 
    542634            return $error; 
    543635        } 
     
    637729     * @param string The userid to authenticate as. 
    638730     * @param string The password to authenticate with. 
     731     * @param string The optional authorization proxy identifier. 
    639732     * 
    640733     * @return mixed Returns a PEAR_Error with an error message on any 
     
    643736     * @since  1.1.0 
    644737     */ 
    645     function _authPlain($uid, $pwd) 
     738    function _authPlain($uid, $pwd, $authz = '') 
    646739    { 
    647740        if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { 
     
    657750        } 
    658751 
    659         $auth_str = base64_encode(chr(0) . $uid . chr(0) . $pwd); 
     752        $auth_str = base64_encode($authz . chr(0) . $uid . chr(0) . $pwd); 
    660753 
    661754        if (PEAR::isError($error = $this->_put($auth_str))) { 
     
    691784 
    692785        return true; 
     786    } 
     787 
     788    /** 
     789     * Return the list of SMTP service extensions advertised by the server. 
     790     * 
     791     * @return array The list of SMTP service extensions. 
     792     * @access public 
     793     * @since 1.3 
     794     */ 
     795    function getServiceExtensions() 
     796    { 
     797        return $this->_esmtp; 
    693798    } 
    694799 
     
    733838            return $error; 
    734839        } 
    735         if (PEAR::isError($error = $this->_parseResponse(250))) { 
     840        if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { 
    736841            return $error; 
    737842        } 
     
    763868            return $error; 
    764869        } 
    765         if (PEAR::isError($error = $this->_parseResponse(array(250, 251)))) { 
     870        if (PEAR::isError($error = $this->_parseResponse(array(250, 251), $this->pipelining))) { 
    766871            return $error; 
    767872        } 
     
    798903     * Send the DATA command. 
    799904     * 
    800      * @param string $data  The message body to send. 
     905     * @param mixed $data     The message data, either as a string or an open 
     906     *                        file resource. 
     907     * @param string $headers The message headers.  If $headers is provided, 
     908     *                        $data is assumed to contain only body data. 
    801909     * 
    802910     * @return mixed Returns a PEAR_Error with an error message on any 
     
    805913     * @since  1.0 
    806914     */ 
    807     function data($data) 
    808     { 
    809         /* RFC 1870, section 3, subsection 3 states "a value of zero 
    810          * indicates that no fixed maximum message size is in force". 
    811          * Furthermore, it says that if "the parameter is omitted no 
    812          * information is conveyed about the server's fixed maximum 
    813          * message size". */ 
    814         if (isset($this->_esmtp['SIZE']) && ($this->_esmtp['SIZE'] > 0)) { 
    815             if (strlen($data) >= $this->_esmtp['SIZE']) { 
    816                 $this->disconnect(); 
    817                 return PEAR::raiseError('Message size excedes the server limit'); 
    818             } 
    819         } 
    820  
    821         /* Quote the data based on the SMTP standards. */ 
    822         $this->quotedata($data); 
    823  
     915    function data($data, $headers = null) 
     916    { 
     917        /* Verify that $data is a supported type. */ 
     918        if (!is_string($data) && !is_resource($data)) { 
     919            return PEAR::raiseError('Expected a string or file resource'); 
     920        } 
     921 
     922        /* Start by considering the size of the optional headers string.  We 
     923         * also account for the addition 4 character "\r\n\r\n" separator 
     924         * sequence. */ 
     925        $size = (is_null($headers)) ? 0 : strlen($headers) + 4; 
     926 
     927        if (is_resource($data)) { 
     928            $stat = fstat($data); 
     929            if ($stat === false) { 
     930                return PEAR::raiseError('Failed to get file size'); 
     931            } 
     932            $size += $stat['size']; 
     933        } else { 
     934            $size += strlen($data); 
     935        } 
     936 
     937        /* RFC 1870, section 3, subsection 3 states "a value of zero indicates 
     938         * that no fixed maximum message size is in force".  Furthermore, it 
     939         * says that if "the parameter is omitted no information is conveyed 
     940         * about the server's fixed maximum message size". */ 
     941        $limit = (isset($this->_esmtp['SIZE'])) ? $this->_esmtp['SIZE'] : 0; 
     942        if ($limit > 0 && $size >= $limit) { 
     943            $this->disconnect(); 
     944            return PEAR::raiseError('Message size exceeds server limit'); 
     945        } 
     946 
     947        /* Initiate the DATA command. */ 
    824948        if (PEAR::isError($error = $this->_put('DATA'))) { 
    825949            return $error; 
     
    829953        } 
    830954 
    831         if (PEAR::isError($result = $this->_send($data . "\r\n.\r\n"))) { 
     955        /* If we have a separate headers string, send it first. */ 
     956        if (!is_null($headers)) { 
     957            $this->quotedata($headers); 
     958            if (PEAR::isError($result = $this->_send($headers . "\r\n\r\n"))) { 
     959                return $result; 
     960            } 
     961        } 
     962 
     963        /* Now we can send the message body data. */ 
     964        if (is_resource($data)) { 
     965            /* Stream the contents of the file resource out over our socket  
     966             * connection, line by line.  Each line must be run through the  
     967             * quoting routine. */ 
     968            while ($line = fgets($data, 1024)) { 
     969                $this->quotedata($line); 
     970                if (PEAR::isError($result = $this->_send($line))) { 
     971                    return $result; 
     972                } 
     973            } 
     974        } else { 
     975            /* 
     976             * Break up the data by sending one chunk (up to 512k) at a time.   
     977             * This approach reduces our peak memory usage. 
     978             */ 
     979            for ($offset = 0; $offset < $size;) { 
     980                $end = $offset + 512000; 
     981 
     982                /* 
     983                 * Ensure we don't read beyond our data size or span multiple  
     984                 * lines.  quotedata() can't properly handle character data  
     985                 * that's split across two line break boundaries. 
     986                 */ 
     987                if ($end >= $size) { 
     988                    $end = $size; 
     989                } else { 
     990                    for (; $end < $size; $end++) { 
     991                        if ($data[$end] != "\n") { 
     992                            break; 
     993                        } 
     994                    } 
     995                } 
     996 
     997                /* Extract our chunk and run it through the quoting routine. */ 
     998                $chunk = substr($data, $offset, $end - $offset); 
     999                $this->quotedata($chunk); 
     1000 
     1001                /* If we run into a problem along the way, abort. */ 
     1002                if (PEAR::isError($result = $this->_send($chunk))) { 
     1003                    return $result; 
     1004                } 
     1005 
     1006                /* Advance the offset to the end of this chunk. */ 
     1007                $offset = $end; 
     1008            } 
     1009        } 
     1010 
     1011        /* Finally, send the DATA terminator sequence. */ 
     1012        if (PEAR::isError($result = $this->_send("\r\n.\r\n"))) { 
    8321013            return $result; 
    8331014        } 
    834         if (PEAR::isError($error = $this->_parseResponse(250))) { 
     1015 
     1016        /* Verify that the data was successfully received by the server. */ 
     1017        if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { 
    8351018            return $error; 
    8361019        } 
     
    8541037            return $error; 
    8551038        } 
    856         if (PEAR::isError($error = $this->_parseResponse(250))) { 
     1039        if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { 
    8571040            return $error; 
    8581041        } 
     
    8931076            return $error; 
    8941077        } 
    895         if (PEAR::isError($error = $this->_parseResponse(250))) { 
     1078        if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { 
    8961079            return $error; 
    8971080        } 
     
    9321115            return $error; 
    9331116        } 
    934         if (PEAR::isError($error = $this->_parseResponse(250))) { 
     1117        if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { 
    9351118            return $error; 
    9361119        } 
     
    9691152            return $error; 
    9701153        } 
    971         if (PEAR::isError($error = $this->_parseResponse(250))) { 
     1154        if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { 
    9721155            return $error; 
    9731156        } 
Note: See TracChangeset for help on using the changeset viewer.