source: branches/dev/data/module/Net/SMTP.php @ 13183

Revision 13183, 31.2 KB checked in by matsumoto, 15 years ago (diff)
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: SMTP.php,v 1.58 2007/03/28 04:53:34 chagenbu Exp $
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 (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(true, STREAM_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(250, 251)))) {
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(250, 252)))) {
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}
Note: See TracBrowser for help on using the repository browser.