Net_SMTP
[ class tree: Net_SMTP ] [ index: Net_SMTP ] [ all elements ]

Source for file SMTP.php

Documentation is available at SMTP.php

  1. <?php
  2. /* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Chuck Hagenbuch <chuck@horde.org>                           |
  17. // |          Jon Parise <jon@php.net>                                    |
  18. // |          Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>      |
  19. // +----------------------------------------------------------------------+
  20. //
  21. // $Id: SMTP.php,v 1.58 2007/03/28 04:53:34 chagenbu Exp $
  22.  
  23. require_once 'PEAR.php';
  24. require_once 'Net/Socket.php';
  25.  
  26. /**
  27.  * Provides an implementation of the SMTP protocol using PEAR's
  28.  * Net_Socket:: class.
  29.  *
  30.  * @package Net_SMTP
  31.  * @author  Chuck Hagenbuch <chuck@horde.org>
  32.  * @author  Jon Parise <jon@php.net>
  33.  * @author  Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar>
  34.  *
  35.  * @example basic.php   A basic implementation of the Net_SMTP package.
  36.  */
  37. class Net_SMTP
  38. {
  39.     /**
  40.      * The server to connect to.
  41.      * @var string 
  42.      * @access public
  43.      */
  44.     var $host = 'localhost';
  45.  
  46.     /**
  47.      * The port to connect to.
  48.      * @var int 
  49.      * @access public
  50.      */
  51.     var $port = 25;
  52.  
  53.     /**
  54.      * The value to give when sending EHLO or HELO.
  55.      * @var string 
  56.      * @access public
  57.      */
  58.     var $localhost = 'localhost';
  59.  
  60.     /**
  61.      * List of supported authentication methods, in preferential order.
  62.      * @var array 
  63.      * @access public
  64.      */
  65.     var $auth_methods = array('DIGEST-MD5''CRAM-MD5''LOGIN''PLAIN');
  66.  
  67.     /**
  68.      * Should debugging output be enabled?
  69.      * @var boolean 
  70.      * @access private
  71.      */
  72.     var $_debug = false;
  73.  
  74.     /**
  75.      * The socket resource being used to connect to the SMTP server.
  76.      * @var resource 
  77.      * @access private
  78.      */
  79.     var $_socket = null;
  80.  
  81.     /**
  82.      * The most recent server response code.
  83.      * @var int 
  84.      * @access private
  85.      */
  86.     var $_code = -1;
  87.  
  88.     /**
  89.      * The most recent server response arguments.
  90.      * @var array 
  91.      * @access private
  92.      */
  93.     var $_arguments = array();
  94.  
  95.     /**
  96.      * Stores detected features of the SMTP server.
  97.      * @var array 
  98.      * @access private
  99.      */
  100.     var $_esmtp = array();
  101.  
  102.     /**
  103.      * Instantiates a new Net_SMTP object, overriding any defaults
  104.      * with parameters that are passed in.
  105.      *
  106.      * If you have SSL support in PHP, you can connect to a server
  107.      * over SSL using an 'ssl://' prefix:
  108.      *
  109.      *   // 465 is a common smtps port.
  110.      *   $smtp = new Net_SMTP('ssl://mail.host.com', 465);
  111.      *   $smtp->connect();
  112.      *
  113.      * @param string  $host       The server to connect to.
  114.      * @param integer $port       The port to connect to.
  115.      * @param string  $localhost  The value to give when sending EHLO or HELO.
  116.      *
  117.      * @access  public
  118.      * @since   1.0
  119.      */
  120.     function Net_SMTP($host = null$port = null$localhost = null)
  121.     {
  122.         if (isset($host)) $this->host = $host;
  123.         if (isset($port)) $this->port = $port;
  124.         if (isset($localhost)) $this->localhost = $localhost;
  125.  
  126.         $this->_socket = new Net_Socket();
  127.  
  128.         /*
  129.          * Include the Auth_SASL package.  If the package is not available,
  130.          * we disable the authentication methods that depend upon it.
  131.          */
  132.         if ((@include_once 'Auth/SASL.php'=== false{
  133.             $pos array_search('DIGEST-MD5'$this->auth_methods);
  134.             unset($this->auth_methods[$pos]);
  135.             $pos array_search('CRAM-MD5'$this->auth_methods);
  136.             unset($this->auth_methods[$pos]);
  137.         }
  138.     }
  139.  
  140.     /**
  141.      * Set the value of the debugging flag.
  142.      *
  143.      * @param   boolean $debug      New value for the debugging flag.
  144.      *
  145.      * @access  public
  146.      * @since   1.1.0
  147.      */
  148.     function setDebug($debug)
  149.     {
  150.         $this->_debug $debug;
  151.     }
  152.  
  153.     /**
  154.      * Send the given string of data to the server.
  155.      *
  156.      * @param   string  $data       The string of data to send.
  157.      *
  158.      * @return  mixed   True on success or a PEAR_Error object on failure.
  159.      *
  160.      * @access  private
  161.      * @since   1.1.0
  162.      */
  163.     function _send($data)
  164.     {
  165.         if ($this->_debug{
  166.             echo "DEBUG: Send: $data\n";
  167.         }
  168.  
  169.         if (PEAR::isError($error $this->_socket->write($data))) {
  170.             return PEAR::raiseError('Failed to write to socket: ' .
  171.                                     $error->getMessage());
  172.         }
  173.  
  174.         return true;
  175.     }
  176.  
  177.     /**
  178.      * Send a command to the server with an optional string of
  179.      * arguments.  A carriage return / linefeed (CRLF) sequence will
  180.      * be appended to each command string before it is sent to the
  181.      * SMTP server - an error will be thrown if the command string
  182.      * already contains any newline characters. Use _send() for
  183.      * commands that must contain newlines.
  184.      *
  185.      * @param   string  $command    The SMTP command to send to the server.
  186.      * @param   string  $args       A string of optional arguments to append
  187.      *                               to the command.
  188.      *
  189.      * @return  mixed   The result of the _send() call.
  190.      *
  191.      * @access  private
  192.      * @since   1.1.0
  193.      */
  194.     function _put($command$args '')
  195.     {
  196.         if (!empty($args)) {
  197.             $command .= ' ' $args;
  198.         }
  199.  
  200.         if (strcspn($command"\r\n"!== strlen($command)) {
  201.             return PEAR::raiseError('Commands cannot contain newlines');
  202.         }
  203.  
  204.         return $this->_send($command "\r\n");
  205.     }
  206.  
  207.     /**
  208.      * Read a reply from the SMTP server.  The reply consists of a response
  209.      * code and a response message.
  210.      *
  211.      * @param   mixed   $valid      The set of valid response codes.  These
  212.      *                               may be specified as an array of integer
  213.      *                               values or as a single integer value.
  214.      *
  215.      * @return  mixed   True if the server returned a valid response code or
  216.      *                   a PEAR_Error object is an error condition is reached.
  217.      *
  218.      * @access  private
  219.      * @since   1.1.0
  220.      *
  221.      * @see     getResponse
  222.      */
  223.     function _parseResponse($valid)
  224.     {
  225.         $this->_code = -1;
  226.         $this->_arguments = array();
  227.  
  228.         while ($line $this->_socket->readLine()) {
  229.             if ($this->_debug{
  230.                 echo "DEBUG: Recv: $line\n";
  231.             }
  232.  
  233.             /* If we receive an empty line, the connection has been closed. */
  234.             if (empty($line)) {
  235.                 $this->disconnect();
  236.                 return PEAR::raiseError('Connection was unexpectedly closed');
  237.             }
  238.  
  239.             /* Read the code and store the rest in the arguments array. */
  240.             $code substr($line03);
  241.             $this->_arguments[trim(substr($line4));
  242.  
  243.             /* Check the syntax of the response code. */
  244.             if (is_numeric($code)) {
  245.                 $this->_code = (int)$code;
  246.             else {
  247.                 $this->_code = -1;
  248.                 break;
  249.             }
  250.  
  251.             /* If this is not a multiline response, we're done. */
  252.             if (substr($line31!= '-'{
  253.                 break;
  254.             }
  255.         }
  256.  
  257.         /* Compare the server's response code with the valid code. */
  258.         if (is_int($valid&& ($this->_code === $valid)) {
  259.             return true;
  260.         }
  261.  
  262.         /* If we were given an array of valid response codes, check each one. */
  263.         if (is_array($valid)) {
  264.             foreach ($valid as $valid_code{
  265.                 if ($this->_code === $valid_code{
  266.                     return true;
  267.                 }
  268.             }
  269.         }
  270.  
  271.         return PEAR::raiseError('Invalid response code received from server',
  272.                                 $this->_code);
  273.     }
  274.  
  275.     /**
  276.      * Return a 2-tuple containing the last response from the SMTP server.
  277.      *
  278.      * @return  array   A two-element array: the first element contains the
  279.      *                   response code as an integer and the second element
  280.      *                   contains the response's arguments as a string.
  281.      *
  282.      * @access  public
  283.      * @since   1.1.0
  284.      */
  285.     function getResponse()
  286.     {
  287.         return array($this->_codejoin("\n"$this->_arguments));
  288.     }
  289.  
  290.     /**
  291.      * Attempt to connect to the SMTP server.
  292.      *
  293.      * @param   int     $timeout    The timeout value (in seconds) for the
  294.      *                               socket connection.
  295.      * @param   bool    $persistent Should a persistent socket connection
  296.      *                               be used?
  297.      *
  298.      * @return mixed Returns a PEAR_Error with an error message on any
  299.      *                kind of failure, or true on success.
  300.      * @access public
  301.      * @since  1.0
  302.      */
  303.     function connect($timeout = null$persistent = false)
  304.     {
  305.         $result $this->_socket->connect($this->host$this->port,
  306.                                           $persistent$timeout);
  307.         if (PEAR::isError($result)) {
  308.             return PEAR::raiseError('Failed to connect socket: ' .
  309.                                     $result->getMessage());
  310.         }
  311.  
  312.         if (PEAR::isError($error $this->_parseResponse(220))) {
  313.             return $error;
  314.         }
  315.         if (PEAR::isError($error $this->_negotiate())) {
  316.             return $error;
  317.         }
  318.  
  319.         return true;
  320.     }
  321.  
  322.     /**
  323.      * Attempt to disconnect from the SMTP server.
  324.      *
  325.      * @return mixed Returns a PEAR_Error with an error message on any
  326.      *                kind of failure, or true on success.
  327.      * @access public
  328.      * @since  1.0
  329.      */
  330.     function disconnect()
  331.     {
  332.         if (PEAR::isError($error $this->_put('QUIT'))) {
  333.             return $error;
  334.         }
  335.         if (PEAR::isError($error $this->_parseResponse(221))) {
  336.             return $error;
  337.         }
  338.         if (PEAR::isError($error $this->_socket->disconnect())) {
  339.             return PEAR::raiseError('Failed to disconnect socket: ' .
  340.                                     $error->getMessage());
  341.         }
  342.  
  343.         return true;
  344.     }
  345.  
  346.     /**
  347.      * Attempt to send the EHLO command and obtain a list of ESMTP
  348.      * extensions available, and failing that just send HELO.
  349.      *
  350.      * @return mixed Returns a PEAR_Error with an error message on any
  351.      *                kind of failure, or true on success.
  352.      *
  353.      * @access private
  354.      * @since  1.1.0
  355.      */
  356.     function _negotiate()
  357.     {
  358.         if (PEAR::isError($error $this->_put('EHLO'$this->localhost))) {
  359.             return $error;
  360.         }
  361.  
  362.         if (PEAR::isError($this->_parseResponse(250))) {
  363.             /* If we receive a 503 response, we're already authenticated. */
  364.             if ($this->_code === 503{
  365.                 return true;
  366.             }
  367.  
  368.             /* If the EHLO failed, try the simpler HELO command. */
  369.             if (PEAR::isError($error $this->_put('HELO'$this->localhost))) {
  370.                 return $error;
  371.             }
  372.             if (PEAR::isError($this->_parseResponse(250))) {
  373.                 return PEAR::raiseError('HELO was not accepted: '$this->_code);
  374.             }
  375.  
  376.             return true;
  377.         }
  378.  
  379.         foreach ($this->_arguments as $argument{
  380.             $verb strtok($argument' ');
  381.             $arguments substr($argumentstrlen($verb+ 1,
  382.                                 strlen($argumentstrlen($verb- 1);
  383.             $this->_esmtp[$verb$arguments;
  384.         }
  385.  
  386.         return true;
  387.     }
  388.  
  389.     /**
  390.      * Returns the name of the best authentication method that the server
  391.      * has advertised.
  392.      *
  393.      * @return mixed    Returns a string containing the name of the best
  394.      *                   supported authentication method or a PEAR_Error object
  395.      *                   if a failure condition is encountered.
  396.      * @access private
  397.      * @since  1.1.0
  398.      */
  399.     function _getBestAuthMethod()
  400.     {
  401.         $available_methods explode(' '$this->_esmtp['AUTH']);
  402.  
  403.         foreach ($this->auth_methods as $method{
  404.             if (in_array($method$available_methods)) {
  405.                 return $method;
  406.             }
  407.         }
  408.  
  409.         return PEAR::raiseError('No supported authentication methods');
  410.     }
  411.  
  412.     /**
  413.      * Attempt to do SMTP authentication.
  414.      *
  415.      * @param string The userid to authenticate as.
  416.      * @param string The password to authenticate with.
  417.      * @param string The requested authentication method.  If none is
  418.      *                specified, the best supported method will be used.
  419.      *
  420.      * @return mixed Returns a PEAR_Error with an error message on any
  421.      *                kind of failure, or true on success.
  422.      * @access public
  423.      * @since  1.0
  424.      */
  425.     function auth($uid$pwd $method '')
  426.     {
  427.         if (empty($this->_esmtp['AUTH'])) {
  428.             if (version_compare(PHP_VERSION'5.1.0''>=')) {
  429.                 if (!isset($this->_esmtp['STARTTLS'])) {
  430.                     return PEAR::raiseError('SMTP server does not support authentication');
  431.                 }
  432.                 if (PEAR::isError($result $this->_put('STARTTLS'))) {
  433.                     return $result;
  434.                 }
  435.                 if (PEAR::isError($result $this->_parseResponse(220))) {
  436.                     return $result;
  437.                 }
  438.                 if (PEAR::isError($result $this->_socket->enableCrypto(trueSTREAM_CRYPTO_METHOD_TLS_CLIENT))) {
  439.                     return $result;
  440.                 elseif ($result !== true{
  441.                     return PEAR::raiseError('STARTTLS failed');
  442.                 }
  443.  
  444.                 /* Send EHLO again to recieve the AUTH string from the
  445.                  * SMTP server. */
  446.                 $this->_negotiate();
  447.                 if (empty($this->_esmtp['AUTH'])) {
  448.                     return PEAR::raiseError('SMTP server does not support authentication');
  449.                 }
  450.             else {
  451.                 return PEAR::raiseError('SMTP server does not support authentication');
  452.             }
  453.         }
  454.  
  455.         /* If no method has been specified, get the name of the best
  456.          * supported method advertised by the SMTP server. */
  457.         if (empty($method)) {
  458.             if (PEAR::isError($method $this->_getBestAuthMethod())) {
  459.                 /* Return the PEAR_Error object from _getBestAuthMethod(). */
  460.                 return $method;
  461.             }
  462.         else {
  463.             $method strtoupper($method);
  464.             if (!in_array($method$this->auth_methods)) {
  465.                 return PEAR::raiseError("$method is not a supported authentication method");
  466.             }
  467.         }
  468.  
  469.         switch ($method{
  470.         case 'DIGEST-MD5':
  471.             $result $this->_authDigest_MD5($uid$pwd);
  472.             break;
  473.  
  474.         case 'CRAM-MD5':
  475.             $result $this->_authCRAM_MD5($uid$pwd);
  476.             break;
  477.  
  478.         case 'LOGIN':
  479.             $result $this->_authLogin($uid$pwd);
  480.             break;
  481.  
  482.         case 'PLAIN':
  483.             $result $this->_authPlain($uid$pwd);
  484.             break;
  485.  
  486.         default:
  487.             $result = PEAR::raiseError("$method is not a supported authentication method");
  488.             break;
  489.         }
  490.  
  491.         /* If an error was encountered, return the PEAR_Error object. */
  492.         if (PEAR::isError($result)) {
  493.             return $result;
  494.         }
  495.  
  496.         return true;
  497.     }
  498.  
  499.     /**
  500.      * Authenticates the user using the DIGEST-MD5 method.
  501.      *
  502.      * @param string The userid to authenticate as.
  503.      * @param string The password to authenticate with.
  504.      *
  505.      * @return mixed Returns a PEAR_Error with an error message on any
  506.      *                kind of failure, or true on success.
  507.      * @access private
  508.      * @since  1.1.0
  509.      */
  510.     function _authDigest_MD5($uid$pwd)
  511.     {
  512.         if (PEAR::isError($error $this->_put('AUTH''DIGEST-MD5'))) {
  513.             return $error;
  514.         }
  515.         /* 334: Continue authentication request */
  516.         if (PEAR::isError($error $this->_parseResponse(334))) {
  517.             /* 503: Error: already authenticated */
  518.             if ($this->_code === 503{
  519.                 return true;
  520.             }
  521.             return $error;
  522.         }
  523.  
  524.         $challenge base64_decode($this->_arguments[0]);
  525.         $digest &Auth_SASL::factory('digestmd5');
  526.         $auth_str base64_encode($digest->getResponse($uid$pwd$challenge,
  527.                                                        $this->host"smtp"));
  528.  
  529.         if (PEAR::isError($error $this->_put($auth_str))) {
  530.             return $error;
  531.         }
  532.         /* 334: Continue authentication request */
  533.         if (PEAR::isError($error $this->_parseResponse(334))) {
  534.             return $error;
  535.         }
  536.  
  537.         /* We don't use the protocol's third step because SMTP doesn't
  538.          * allow subsequent authentication, so we just silently ignore
  539.          * it. */
  540.         if (PEAR::isError($error $this->_put(' '))) {
  541.             return $error;
  542.         }
  543.         /* 235: Authentication successful */
  544.         if (PEAR::isError($error $this->_parseResponse(235))) {
  545.             return $error;
  546.         }
  547.     }
  548.  
  549.     /**
  550.      * Authenticates the user using the CRAM-MD5 method.
  551.      *
  552.      * @param string The userid to authenticate as.
  553.      * @param string The password to authenticate with.
  554.      *
  555.      * @return mixed Returns a PEAR_Error with an error message on any
  556.      *                kind of failure, or true on success.
  557.      * @access private
  558.      * @since  1.1.0
  559.      */
  560.     function _authCRAM_MD5($uid$pwd)
  561.     {
  562.         if (PEAR::isError($error $this->_put('AUTH''CRAM-MD5'))) {
  563.             return $error;
  564.         }
  565.         /* 334: Continue authentication request */
  566.         if (PEAR::isError($error $this->_parseResponse(334))) {
  567.             /* 503: Error: already authenticated */
  568.             if ($this->_code === 503{
  569.                 return true;
  570.             }
  571.             return $error;
  572.         }
  573.  
  574.         $challenge base64_decode($this->_arguments[0]);
  575.         $cram &Auth_SASL::factory('crammd5');
  576.         $auth_str base64_encode($cram->getResponse($uid$pwd$challenge));
  577.  
  578.         if (PEAR::isError($error $this->_put($auth_str))) {
  579.             return $error;
  580.         }
  581.  
  582.         /* 235: Authentication successful */
  583.         if (PEAR::isError($error $this->_parseResponse(235))) {
  584.             return $error;
  585.         }
  586.     }
  587.  
  588.     /**
  589.      * Authenticates the user using the LOGIN method.
  590.      *
  591.      * @param string The userid to authenticate as.
  592.      * @param string The password to authenticate with.
  593.      *
  594.      * @return mixed Returns a PEAR_Error with an error message on any
  595.      *                kind of failure, or true on success.
  596.      * @access private
  597.      * @since  1.1.0
  598.      */
  599.     function _authLogin($uid$pwd)
  600.     {
  601.         if (PEAR::isError($error $this->_put('AUTH''LOGIN'))) {
  602.             return $error;
  603.         }
  604.         /* 334: Continue authentication request */
  605.         if (PEAR::isError($error $this->_parseResponse(334))) {
  606.             /* 503: Error: already authenticated */
  607.             if ($this->_code === 503{
  608.                 return true;
  609.             }
  610.             return $error;
  611.         }
  612.  
  613.         if (PEAR::isError($error $this->_put(base64_encode($uid)))) {
  614.             return $error;
  615.         }
  616.         /* 334: Continue authentication request */
  617.         if (PEAR::isError($error $this->_parseResponse(334))) {
  618.             return $error;
  619.         }
  620.  
  621.         if (PEAR::isError($error $this->_put(base64_encode($pwd)))) {
  622.             return $error;
  623.         }
  624.  
  625.         /* 235: Authentication successful */
  626.         if (PEAR::isError($error $this->_parseResponse(235))) {
  627.             return $error;
  628.         }
  629.  
  630.         return true;
  631.     }
  632.  
  633.     /**
  634.      * Authenticates the user using the PLAIN method.
  635.      *
  636.      * @param string The userid to authenticate as.
  637.      * @param string The password to authenticate with.
  638.      *
  639.      * @return mixed Returns a PEAR_Error with an error message on any
  640.      *                kind of failure, or true on success.
  641.      * @access private
  642.      * @since  1.1.0
  643.      */
  644.     function _authPlain($uid$pwd)
  645.     {
  646.         if (PEAR::isError($error $this->_put('AUTH''PLAIN'))) {
  647.             return $error;
  648.         }
  649.         /* 334: Continue authentication request */
  650.         if (PEAR::isError($error $this->_parseResponse(334))) {
  651.             /* 503: Error: already authenticated */
  652.             if ($this->_code === 503{
  653.                 return true;
  654.             }
  655.             return $error;
  656.         }
  657.  
  658.         $auth_str base64_encode(chr(0$uid chr(0$pwd);
  659.  
  660.         if (PEAR::isError($error $this->_put($auth_str))) {
  661.             return $error;
  662.         }
  663.  
  664.         /* 235: Authentication successful */
  665.         if (PEAR::isError($error $this->_parseResponse(235))) {
  666.             return $error;
  667.         }
  668.  
  669.         return true;
  670.     }
  671.  
  672.     /**
  673.      * Send the HELO command.
  674.      *
  675.      * @param string The domain name to say we are.
  676.      *
  677.      * @return mixed Returns a PEAR_Error with an error message on any
  678.      *                kind of failure, or true on success.
  679.      * @access public
  680.      * @since  1.0
  681.      */
  682.     function helo($domain)
  683.     {
  684.         if (PEAR::isError($error $this->_put('HELO'$domain))) {
  685.             return $error;
  686.         }
  687.         if (PEAR::isError($error $this->_parseResponse(250))) {
  688.             return $error;
  689.         }
  690.  
  691.         return true;
  692.     }
  693.  
  694.     /**
  695.      * Send the MAIL FROM: command.
  696.      *
  697.      * @param string $sender    The sender (reverse path) to set.
  698.      * @param string $params    String containing additional MAIL parameters,
  699.      *                           such as the NOTIFY flags defined by RFC 1891
  700.      *                           or the VERP protocol.
  701.      *
  702.      *                           If $params is an array, only the 'verp' option
  703.      *                           is supported.  If 'verp' is true, the XVERP
  704.      *                           parameter is appended to the MAIL command.  If
  705.      *                           the 'verp' value is a string, the full
  706.      *                           XVERP=value parameter is appended.
  707.      *
  708.      * @return mixed Returns a PEAR_Error with an error message on any
  709.      *                kind of failure, or true on success.
  710.      * @access public
  711.      * @since  1.0
  712.      */
  713.     function mailFrom($sender$params = null)
  714.     {
  715.         $args = "FROM:<$sender>";
  716.  
  717.         /* Support the deprecated array form of $params. */
  718.         if (is_array($params&& isset($params['verp'])) {
  719.             /* XVERP */
  720.             if ($params['verp'=== true{
  721.                 $args .= ' XVERP';
  722.  
  723.             /* XVERP=something */
  724.             elseif (trim($params['verp'])) {
  725.                 $args .= ' XVERP=' $params['verp'];
  726.             }
  727.         elseif (is_string($params)) {
  728.             $args .= ' ' $params;
  729.         }
  730.  
  731.         if (PEAR::isError($error $this->_put('MAIL'$args))) {
  732.             return $error;
  733.         }
  734.         if (PEAR::isError($error $this->_parseResponse(250))) {
  735.             return $error;
  736.         }
  737.  
  738.         return true;
  739.     }
  740.  
  741.     /**
  742.      * Send the RCPT TO: command.
  743.      *
  744.      * @param string $recipient The recipient (forward path) to add.
  745.      * @param string $params    String containing additional RCPT parameters,
  746.      *                           such as the NOTIFY flags defined by RFC 1891.
  747.      *
  748.      * @return mixed Returns a PEAR_Error with an error message on any
  749.      *                kind of failure, or true on success.
  750.      *
  751.      * @access public
  752.      * @since  1.0
  753.      */
  754.     function rcptTo($recipient$params = null)
  755.     {
  756.         $args = "TO:<$recipient>";
  757.         if (is_string($params)) {
  758.             $args .= ' ' $params;
  759.         }
  760.  
  761.         if (PEAR::isError($error $this->_put('RCPT'$args))) {
  762.             return $error;
  763.         }
  764.         if (PEAR::isError($error $this->_parseResponse(array(250251)))) {
  765.             return $error;
  766.         }
  767.  
  768.         return true;
  769.     }
  770.  
  771.     /**
  772.      * Quote the data so that it meets SMTP standards.
  773.      *
  774.      * This is provided as a separate public function to facilitate
  775.      * easier overloading for the cases where it is desirable to
  776.      * customize the quoting behavior.
  777.      *
  778.      * @param string $data  The message text to quote. The string must be passed
  779.      *                       by reference, and the text will be modified in place.
  780.      *
  781.      * @access public
  782.      * @since  1.2
  783.      */
  784.     function quotedata(&$data)
  785.     {
  786.         /* Change Unix (\n) and Mac (\r) linefeeds into
  787.          * Internet-standard CRLF (\r\n) linefeeds. */
  788.         $data preg_replace(array('/(?<!\r)\n/','/\r(?!\n)/')"\r\n"$data);
  789.  
  790.         /* Because a single leading period (.) signifies an end to the
  791.          * data, legitimate leading periods need to be "doubled"
  792.          * (e.g. '..'). */
  793.         $data str_replace("\n.""\n.."$data);
  794.     }
  795.  
  796.     /**
  797.      * Send the DATA command.
  798.      *
  799.      * @param string $data  The message body to send.
  800.      *
  801.      * @return mixed Returns a PEAR_Error with an error message on any
  802.      *                kind of failure, or true on success.
  803.      * @access public
  804.      * @since  1.0
  805.      */
  806.     function data($data)
  807.     {
  808.         /* RFC 1870, section 3, subsection 3 states "a value of zero
  809.          * indicates that no fixed maximum message size is in force".
  810.          * Furthermore, it says that if "the parameter is omitted no
  811.          * information is conveyed about the server's fixed maximum
  812.          * message size". */
  813.         if (isset($this->_esmtp['SIZE']&& ($this->_esmtp['SIZE'> 0)) {
  814.             if (strlen($data>= $this->_esmtp['SIZE']{
  815.                 $this->disconnect();
  816.                 return PEAR::raiseError('Message size excedes the server limit');
  817.             }
  818.         }
  819.  
  820.         /* Quote the data based on the SMTP standards. */
  821.         $this->quotedata($data);
  822.  
  823.         if (PEAR::isError($error $this->_put('DATA'))) {
  824.             return $error;
  825.         }
  826.         if (PEAR::isError($error $this->_parseResponse(354))) {
  827.             return $error;
  828.         }
  829.  
  830.         if (PEAR::isError($result $this->_send($data "\r\n.\r\n"))) {
  831.             return $result;
  832.         }
  833.         if (PEAR::isError($error $this->_parseResponse(250))) {
  834.             return $error;
  835.         }
  836.  
  837.         return true;
  838.     }
  839.  
  840.     /**
  841.      * Send the SEND FROM: command.
  842.      *
  843.      * @param string The reverse path to send.
  844.      *
  845.      * @return mixed Returns a PEAR_Error with an error message on any
  846.      *                kind of failure, or true on success.
  847.      * @access public
  848.      * @since  1.2.6
  849.      */
  850.     function sendFrom($path)
  851.     {
  852.         if (PEAR::isError($error $this->_put('SEND'"FROM:<$path>"))) {
  853.             return $error;
  854.         }
  855.         if (PEAR::isError($error $this->_parseResponse(250))) {
  856.             return $error;
  857.         }
  858.  
  859.         return true;
  860.     }
  861.  
  862.     /**
  863.      * Backwards-compatibility wrapper for sendFrom().
  864.      *
  865.      * @param string The reverse path to send.
  866.      *
  867.      * @return mixed Returns a PEAR_Error with an error message on any
  868.      *                kind of failure, or true on success.
  869.      *
  870.      * @access      public
  871.      * @since       1.0
  872.      * @deprecated  1.2.6
  873.      */
  874.     function send_from($path)
  875.     {
  876.         return sendFrom($path);
  877.     }
  878.  
  879.     /**
  880.      * Send the SOML FROM: command.
  881.      *
  882.      * @param string The reverse path to send.
  883.      *
  884.      * @return mixed Returns a PEAR_Error with an error message on any
  885.      *                kind of failure, or true on success.
  886.      * @access public
  887.      * @since  1.2.6
  888.      */
  889.     function somlFrom($path)
  890.     {
  891.         if (PEAR::isError($error $this->_put('SOML'"FROM:<$path>"))) {
  892.             return $error;
  893.         }
  894.         if (PEAR::isError($error $this->_parseResponse(250))) {
  895.             return $error;
  896.         }
  897.  
  898.         return true;
  899.     }
  900.  
  901.     /**
  902.      * Backwards-compatibility wrapper for somlFrom().
  903.      *
  904.      * @param string The reverse path to send.
  905.      *
  906.      * @return mixed Returns a PEAR_Error with an error message on any
  907.      *                kind of failure, or true on success.
  908.      *
  909.      * @access      public
  910.      * @since       1.0
  911.      * @deprecated  1.2.6
  912.      */
  913.     function soml_from($path)
  914.     {
  915.         return somlFrom($path);
  916.     }
  917.  
  918.     /**
  919.      * Send the SAML FROM: command.
  920.      *
  921.      * @param string The reverse path to send.
  922.      *
  923.      * @return mixed Returns a PEAR_Error with an error message on any
  924.      *                kind of failure, or true on success.
  925.      * @access public
  926.      * @since  1.2.6
  927.      */
  928.     function samlFrom($path)
  929.     {
  930.         if (PEAR::isError($error $this->_put('SAML'"FROM:<$path>"))) {
  931.             return $error;
  932.         }
  933.         if (PEAR::isError($error $this->_parseResponse(250))) {
  934.             return $error;
  935.         }
  936.  
  937.         return true;
  938.     }
  939.  
  940.     /**
  941.      * Backwards-compatibility wrapper for samlFrom().
  942.      *
  943.      * @param string The reverse path to send.
  944.      *
  945.      * @return mixed Returns a PEAR_Error with an error message on any
  946.      *                kind of failure, or true on success.
  947.      *
  948.      * @access      public
  949.      * @since       1.0
  950.      * @deprecated  1.2.6
  951.      */
  952.     function saml_from($path)
  953.     {
  954.         return samlFrom($path);
  955.     }
  956.  
  957.     /**
  958.      * Send the RSET command.
  959.      *
  960.      * @return mixed Returns a PEAR_Error with an error message on any
  961.      *                kind of failure, or true on success.
  962.      * @access public
  963.      * @since  1.0
  964.      */
  965.     function rset()
  966.     {
  967.         if (PEAR::isError($error $this->_put('RSET'))) {
  968.             return $error;
  969.         }
  970.         if (PEAR::isError($error $this->_parseResponse(250))) {
  971.             return $error;
  972.         }
  973.  
  974.         return true;
  975.     }
  976.  
  977.     /**
  978.      * Send the VRFY command.
  979.      *
  980.      * @param string The string to verify
  981.      *
  982.      * @return mixed Returns a PEAR_Error with an error message on any
  983.      *                kind of failure, or true on success.
  984.      * @access public
  985.      * @since  1.0
  986.      */
  987.     function vrfy($string)
  988.     {
  989.         /* Note: 251 is also a valid response code */
  990.         if (PEAR::isError($error $this->_put('VRFY'$string))) {
  991.             return $error;
  992.         }
  993.         if (PEAR::isError($error $this->_parseResponse(array(250252)))) {
  994.             return $error;
  995.         }
  996.  
  997.         return true;
  998.     }
  999.  
  1000.     /**
  1001.      * Send the NOOP command.
  1002.      *
  1003.      * @return mixed Returns a PEAR_Error with an error message on any
  1004.      *                kind of failure, or true on success.
  1005.      * @access public
  1006.      * @since  1.0
  1007.      */
  1008.     function noop()
  1009.     {
  1010.         if (PEAR::isError($error $this->_put('NOOP'))) {
  1011.             return $error;
  1012.         }
  1013.         if (PEAR::isError($error $this->_parseResponse(250))) {
  1014.             return $error;
  1015.         }
  1016.  
  1017.         return true;
  1018.     }
  1019.  
  1020.     /**
  1021.      * Backwards-compatibility method.  identifySender()'s functionality is
  1022.      * now handled internally.
  1023.      *
  1024.      * @return  boolean     This method always return true.
  1025.      *
  1026.      * @access  public
  1027.      * @since   1.0
  1028.      */
  1029.     function identifySender()
  1030.     {
  1031.         return true;
  1032.     }
  1033.  
  1034. }

Documentation generated on Mon, 11 Mar 2019 14:57:49 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.