source: subversion/trunk/roundcubemail/program/lib/Net/SMTP.php @ 2171

Last change on this file since 2171 was 2171, checked in by alec, 5 years ago
  • oops, remove console call
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.9 KB
Line 
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$
22
23require_once 'PEAR.php';
24require_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 */
37class 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($line, 0, 3);
241            $this->_arguments[] = trim(substr($line, 4));
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($line, 3, 1) != '-') {
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->_code, join("\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($argument, strlen($verb) + 1,
382                                strlen($argument) - strlen($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 (version_compare(PHP_VERSION, '5.1.0', '>=') && isset($this->_esmtp['STARTTLS'])) {
428
429                if (PEAR::isError($result = $this->_put('STARTTLS'))) {
430                    return $result;
431                }
432                if (PEAR::isError($result = $this->_parseResponse(220))) {
433                    return $result;
434                }
435                if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) {
436                    return $result;
437                } elseif ($result !== true) {
438                    return PEAR::raiseError('STARTTLS failed');
439                }
440
441                /* Send EHLO again to recieve the AUTH string from the
442                 * SMTP server. */
443                $this->_negotiate();
444        }
445       
446        if (empty($this->_esmtp['AUTH'])) {
447            return PEAR::raiseError('SMTP server does not support authentication');
448        }
449
450        /* If no method has been specified, get the name of the best
451         * supported method advertised by the SMTP server. */
452        if (empty($method)) {
453            if (PEAR::isError($method = $this->_getBestAuthMethod())) {
454                /* Return the PEAR_Error object from _getBestAuthMethod(). */
455                return $method;
456            }
457        } else {
458            $method = strtoupper($method);
459            if (!in_array($method, $this->auth_methods)) {
460                return PEAR::raiseError("$method is not a supported authentication method");
461            }
462        }
463
464        switch ($method) {
465        case 'DIGEST-MD5':
466            $result = $this->_authDigest_MD5($uid, $pwd);
467            break;
468
469        case 'CRAM-MD5':
470            $result = $this->_authCRAM_MD5($uid, $pwd);
471            break;
472
473        case 'LOGIN':
474            $result = $this->_authLogin($uid, $pwd);
475            break;
476
477        case 'PLAIN':
478            $result = $this->_authPlain($uid, $pwd);
479            break;
480
481        default:
482            $result = PEAR::raiseError("$method is not a supported authentication method");
483            break;
484        }
485
486        /* If an error was encountered, return the PEAR_Error object. */
487        if (PEAR::isError($result)) {
488            return $result;
489        }
490
491        return true;
492    }
493
494    /**
495     * Authenticates the user using the DIGEST-MD5 method.
496     *
497     * @param string The userid to authenticate as.
498     * @param string The password to authenticate with.
499     *
500     * @return mixed Returns a PEAR_Error with an error message on any
501     *               kind of failure, or true on success.
502     * @access private
503     * @since  1.1.0
504     */
505    function _authDigest_MD5($uid, $pwd)
506    {
507        if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) {
508            return $error;
509        }
510        /* 334: Continue authentication request */
511        if (PEAR::isError($error = $this->_parseResponse(334))) {
512            /* 503: Error: already authenticated */
513            if ($this->_code === 503) {
514                return true;
515            }
516            return $error;
517        }
518
519        $challenge = base64_decode($this->_arguments[0]);
520        $digest = &Auth_SASL::factory('digestmd5');
521        $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge,
522                                                       $this->host, "smtp"));
523
524        if (PEAR::isError($error = $this->_put($auth_str))) {
525            return $error;
526        }
527        /* 334: Continue authentication request */
528        if (PEAR::isError($error = $this->_parseResponse(334))) {
529            return $error;
530        }
531
532        /* We don't use the protocol's third step because SMTP doesn't
533         * allow subsequent authentication, so we just silently ignore
534         * it. */
535        if (PEAR::isError($error = $this->_put(' '))) {
536            return $error;
537        }
538        /* 235: Authentication successful */
539        if (PEAR::isError($error = $this->_parseResponse(235))) {
540            return $error;
541        }
542    }
543
544    /**
545     * Authenticates the user using the CRAM-MD5 method.
546     *
547     * @param string The userid to authenticate as.
548     * @param string The password to authenticate with.
549     *
550     * @return mixed Returns a PEAR_Error with an error message on any
551     *               kind of failure, or true on success.
552     * @access private
553     * @since  1.1.0
554     */
555    function _authCRAM_MD5($uid, $pwd)
556    {
557        if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) {
558            return $error;
559        }
560        /* 334: Continue authentication request */
561        if (PEAR::isError($error = $this->_parseResponse(334))) {
562            /* 503: Error: already authenticated */
563            if ($this->_code === 503) {
564                return true;
565            }
566            return $error;
567        }
568
569        $challenge = base64_decode($this->_arguments[0]);
570        $cram = &Auth_SASL::factory('crammd5');
571        $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
572
573        if (PEAR::isError($error = $this->_put($auth_str))) {
574            return $error;
575        }
576
577        /* 235: Authentication successful */
578        if (PEAR::isError($error = $this->_parseResponse(235))) {
579            return $error;
580        }
581    }
582
583    /**
584     * Authenticates the user using the LOGIN method.
585     *
586     * @param string The userid to authenticate as.
587     * @param string The password to authenticate with.
588     *
589     * @return mixed Returns a PEAR_Error with an error message on any
590     *               kind of failure, or true on success.
591     * @access private
592     * @since  1.1.0
593     */
594    function _authLogin($uid, $pwd)
595    {
596        if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) {
597            return $error;
598        }
599        /* 334: Continue authentication request */
600        if (PEAR::isError($error = $this->_parseResponse(334))) {
601            /* 503: Error: already authenticated */
602            if ($this->_code === 503) {
603                return true;
604            }
605            return $error;
606        }
607
608        if (PEAR::isError($error = $this->_put(base64_encode($uid)))) {
609            return $error;
610        }
611        /* 334: Continue authentication request */
612        if (PEAR::isError($error = $this->_parseResponse(334))) {
613            return $error;
614        }
615
616        if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) {
617            return $error;
618        }
619
620        /* 235: Authentication successful */
621        if (PEAR::isError($error = $this->_parseResponse(235))) {
622            return $error;
623        }
624
625        return true;
626    }
627
628    /**
629     * Authenticates the user using the PLAIN method.
630     *
631     * @param string The userid to authenticate as.
632     * @param string The password to authenticate with.
633     *
634     * @return mixed Returns a PEAR_Error with an error message on any
635     *               kind of failure, or true on success.
636     * @access private
637     * @since  1.1.0
638     */
639    function _authPlain($uid, $pwd)
640    {
641        if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) {
642            return $error;
643        }
644        /* 334: Continue authentication request */
645        if (PEAR::isError($error = $this->_parseResponse(334))) {
646            /* 503: Error: already authenticated */
647            if ($this->_code === 503) {
648                return true;
649            }
650            return $error;
651        }
652
653        $auth_str = base64_encode(chr(0) . $uid . chr(0) . $pwd);
654
655        if (PEAR::isError($error = $this->_put($auth_str))) {
656            return $error;
657        }
658
659        /* 235: Authentication successful */
660        if (PEAR::isError($error = $this->_parseResponse(235))) {
661            return $error;
662        }
663
664        return true;
665    }
666
667    /**
668     * Send the HELO command.
669     *
670     * @param string The domain name to say we are.
671     *
672     * @return mixed Returns a PEAR_Error with an error message on any
673     *               kind of failure, or true on success.
674     * @access public
675     * @since  1.0
676     */
677    function helo($domain)
678    {
679        if (PEAR::isError($error = $this->_put('HELO', $domain))) {
680            return $error;
681        }
682        if (PEAR::isError($error = $this->_parseResponse(250))) {
683            return $error;
684        }
685
686        return true;
687    }
688
689    /**
690     * Send the MAIL FROM: command.
691     *
692     * @param string $sender    The sender (reverse path) to set.
693     * @param string $params    String containing additional MAIL parameters,
694     *                          such as the NOTIFY flags defined by RFC 1891
695     *                          or the VERP protocol.
696     *
697     *                          If $params is an array, only the 'verp' option
698     *                          is supported.  If 'verp' is true, the XVERP
699     *                          parameter is appended to the MAIL command.  If
700     *                          the 'verp' value is a string, the full
701     *                          XVERP=value parameter is appended.
702     *
703     * @return mixed Returns a PEAR_Error with an error message on any
704     *               kind of failure, or true on success.
705     * @access public
706     * @since  1.0
707     */
708    function mailFrom($sender, $params = null)
709    {
710        $args = "FROM:<$sender>";
711
712        /* Support the deprecated array form of $params. */
713        if (is_array($params) && isset($params['verp'])) {
714            /* XVERP */
715            if ($params['verp'] === true) {
716                $args .= ' XVERP';
717
718            /* XVERP=something */
719            } elseif (trim($params['verp'])) {
720                $args .= ' XVERP=' . $params['verp'];
721            }
722        } elseif (is_string($params)) {
723            $args .= ' ' . $params;
724        }
725
726        if (PEAR::isError($error = $this->_put('MAIL', $args))) {
727            return $error;
728        }
729        if (PEAR::isError($error = $this->_parseResponse(250))) {
730            return $error;
731        }
732
733        return true;
734    }
735
736    /**
737     * Send the RCPT TO: command.
738     *
739     * @param string $recipient The recipient (forward path) to add.
740     * @param string $params    String containing additional RCPT parameters,
741     *                          such as the NOTIFY flags defined by RFC 1891.
742     *
743     * @return mixed Returns a PEAR_Error with an error message on any
744     *               kind of failure, or true on success.
745     *
746     * @access public
747     * @since  1.0
748     */
749    function rcptTo($recipient, $params = null)
750    {
751        $args = "TO:<$recipient>";
752        if (is_string($params)) {
753            $args .= ' ' . $params;
754        }
755
756        if (PEAR::isError($error = $this->_put('RCPT', $args))) {
757            return $error;
758        }
759        if (PEAR::isError($error = $this->_parseResponse(array(250, 251)))) {
760            return $error;
761        }
762
763        return true;
764    }
765
766    /**
767     * Quote the data so that it meets SMTP standards.
768     *
769     * This is provided as a separate public function to facilitate
770     * easier overloading for the cases where it is desirable to
771     * customize the quoting behavior.
772     *
773     * @param string $data  The message text to quote. The string must be passed
774     *                      by reference, and the text will be modified in place.
775     *
776     * @access public
777     * @since  1.2
778     */
779    function quotedata(&$data)
780    {
781        /* Change Unix (\n) and Mac (\r) linefeeds into
782         * Internet-standard CRLF (\r\n) linefeeds. */
783        $data = preg_replace(array('/(?<!\r)\n/','/\r(?!\n)/'), "\r\n", $data);
784
785        /* Because a single leading period (.) signifies an end to the
786         * data, legitimate leading periods need to be "doubled"
787         * (e.g. '..'). */
788        $data = str_replace("\n.", "\n..", $data);
789    }
790
791    /**
792     * Send the DATA command.
793     *
794     * @param string $data  The message body to send.
795     *
796     * @return mixed Returns a PEAR_Error with an error message on any
797     *               kind of failure, or true on success.
798     * @access public
799     * @since  1.0
800     */
801    function data($data)
802    {
803        /* RFC 1870, section 3, subsection 3 states "a value of zero
804         * indicates that no fixed maximum message size is in force".
805         * Furthermore, it says that if "the parameter is omitted no
806         * information is conveyed about the server's fixed maximum
807         * message size". */
808        if (isset($this->_esmtp['SIZE']) && ($this->_esmtp['SIZE'] > 0)) {
809            if (strlen($data) >= $this->_esmtp['SIZE']) {
810                $this->disconnect();
811                return PEAR::raiseError('Message size excedes the server limit');
812            }
813        }
814
815        /* Quote the data based on the SMTP standards. */
816        $this->quotedata($data);
817
818        if (PEAR::isError($error = $this->_put('DATA'))) {
819            return $error;
820        }
821        if (PEAR::isError($error = $this->_parseResponse(354))) {
822            return $error;
823        }
824
825        if (PEAR::isError($result = $this->_send($data . "\r\n.\r\n"))) {
826            return $result;
827        }
828        if (PEAR::isError($error = $this->_parseResponse(250))) {
829            return $error;
830        }
831
832        return true;
833    }
834
835    /**
836     * Send the SEND FROM: command.
837     *
838     * @param string The reverse path to send.
839     *
840     * @return mixed Returns a PEAR_Error with an error message on any
841     *               kind of failure, or true on success.
842     * @access public
843     * @since  1.2.6
844     */
845    function sendFrom($path)
846    {
847        if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) {
848            return $error;
849        }
850        if (PEAR::isError($error = $this->_parseResponse(250))) {
851            return $error;
852        }
853
854        return true;
855    }
856
857    /**
858     * Backwards-compatibility wrapper for sendFrom().
859     *
860     * @param string The reverse path to send.
861     *
862     * @return mixed Returns a PEAR_Error with an error message on any
863     *               kind of failure, or true on success.
864     *
865     * @access      public
866     * @since       1.0
867     * @deprecated  1.2.6
868     */
869    function send_from($path)
870    {
871        return sendFrom($path);
872    }
873
874    /**
875     * Send the SOML FROM: command.
876     *
877     * @param string The reverse path to send.
878     *
879     * @return mixed Returns a PEAR_Error with an error message on any
880     *               kind of failure, or true on success.
881     * @access public
882     * @since  1.2.6
883     */
884    function somlFrom($path)
885    {
886        if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) {
887            return $error;
888        }
889        if (PEAR::isError($error = $this->_parseResponse(250))) {
890            return $error;
891        }
892
893        return true;
894    }
895
896    /**
897     * Backwards-compatibility wrapper for somlFrom().
898     *
899     * @param string The reverse path to send.
900     *
901     * @return mixed Returns a PEAR_Error with an error message on any
902     *               kind of failure, or true on success.
903     *
904     * @access      public
905     * @since       1.0
906     * @deprecated  1.2.6
907     */
908    function soml_from($path)
909    {
910        return somlFrom($path);
911    }
912
913    /**
914     * Send the SAML FROM: command.
915     *
916     * @param string The reverse path to send.
917     *
918     * @return mixed Returns a PEAR_Error with an error message on any
919     *               kind of failure, or true on success.
920     * @access public
921     * @since  1.2.6
922     */
923    function samlFrom($path)
924    {
925        if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) {
926            return $error;
927        }
928        if (PEAR::isError($error = $this->_parseResponse(250))) {
929            return $error;
930        }
931
932        return true;
933    }
934
935    /**
936     * Backwards-compatibility wrapper for samlFrom().
937     *
938     * @param string The reverse path to send.
939     *
940     * @return mixed Returns a PEAR_Error with an error message on any
941     *               kind of failure, or true on success.
942     *
943     * @access      public
944     * @since       1.0
945     * @deprecated  1.2.6
946     */
947    function saml_from($path)
948    {
949        return samlFrom($path);
950    }
951
952    /**
953     * Send the RSET command.
954     *
955     * @return mixed Returns a PEAR_Error with an error message on any
956     *               kind of failure, or true on success.
957     * @access public
958     * @since  1.0
959     */
960    function rset()
961    {
962        if (PEAR::isError($error = $this->_put('RSET'))) {
963            return $error;
964        }
965        if (PEAR::isError($error = $this->_parseResponse(250))) {
966            return $error;
967        }
968
969        return true;
970    }
971
972    /**
973     * Send the VRFY command.
974     *
975     * @param string The string to verify
976     *
977     * @return mixed Returns a PEAR_Error with an error message on any
978     *               kind of failure, or true on success.
979     * @access public
980     * @since  1.0
981     */
982    function vrfy($string)
983    {
984        /* Note: 251 is also a valid response code */
985        if (PEAR::isError($error = $this->_put('VRFY', $string))) {
986            return $error;
987        }
988        if (PEAR::isError($error = $this->_parseResponse(array(250, 252)))) {
989            return $error;
990        }
991
992        return true;
993    }
994
995    /**
996     * Send the NOOP command.
997     *
998     * @return mixed Returns a PEAR_Error with an error message on any
999     *               kind of failure, or true on success.
1000     * @access public
1001     * @since  1.0
1002     */
1003    function noop()
1004    {
1005        if (PEAR::isError($error = $this->_put('NOOP'))) {
1006            return $error;
1007        }
1008        if (PEAR::isError($error = $this->_parseResponse(250))) {
1009            return $error;
1010        }
1011
1012        return true;
1013    }
1014
1015    /**
1016     * Backwards-compatibility method.  identifySender()'s functionality is
1017     * now handled internally.
1018     *
1019     * @return  boolean     This method always return true.
1020     *
1021     * @access  public
1022     * @since   1.0
1023     */
1024    function identifySender()
1025    {
1026        return true;
1027    }
1028
1029}
Note: See TracBrowser for help on using the repository browser.