Subversion Repositories Applications.papyrus

Rev

Rev 1372 | Details | Compare with Previous | Last modification | View Log | RSS feed

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