]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - extlib/Mail/smtp.php
Merge branch 'testing' into 0.9.x
[quix0rs-gnu-social.git] / extlib / Mail / smtp.php
1 <?php
2 //
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 // +----------------------------------------------------------------------+
19
20 /** Error: Failed to create a Net_SMTP object */
21 define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
22
23 /** Error: Failed to connect to SMTP server */
24 define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
25
26 /** Error: SMTP authentication failure */
27 define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
28
29 /** Error: No From: address has been provided */
30 define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
31
32 /** Error: Failed to set sender */
33 define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
34
35 /** Error: Failed to add recipient */
36 define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
37
38 /** Error: Failed to send data */
39 define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);
40
41 /**
42  * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
43  * @access public
44  * @package Mail
45  * @version $Revision: 1.33 $
46  */
47 class Mail_smtp extends Mail {
48
49     /**
50      * SMTP connection object.
51      *
52      * @var object
53      * @access private
54      */
55     var $_smtp = null;
56
57     /**
58      * The list of service extension parameters to pass to the Net_SMTP
59      * mailFrom() command.
60      * @var array
61      */
62     var $_extparams = array();
63
64     /**
65      * The SMTP host to connect to.
66      * @var string
67      */
68     var $host = 'localhost';
69
70     /**
71      * The port the SMTP server is on.
72      * @var integer
73      */
74     var $port = 25;
75
76     /**
77      * Should SMTP authentication be used?
78      *
79      * This value may be set to true, false or the name of a specific
80      * authentication method.
81      *
82      * If the value is set to true, the Net_SMTP package will attempt to use
83      * the best authentication method advertised by the remote SMTP server.
84      *
85      * @var mixed
86      */
87     var $auth = false;
88
89     /**
90      * The username to use if the SMTP server requires authentication.
91      * @var string
92      */
93     var $username = '';
94
95     /**
96      * The password to use if the SMTP server requires authentication.
97      * @var string
98      */
99     var $password = '';
100
101     /**
102      * Hostname or domain that will be sent to the remote SMTP server in the
103      * HELO / EHLO message.
104      *
105      * @var string
106      */
107     var $localhost = 'localhost';
108
109     /**
110      * SMTP connection timeout value.  NULL indicates no timeout.
111      *
112      * @var integer
113      */
114     var $timeout = null;
115
116     /**
117      * Turn on Net_SMTP debugging?
118      *
119      * @var boolean $debug
120      */
121     var $debug = false;
122
123     /**
124      * Indicates whether or not the SMTP connection should persist over
125      * multiple calls to the send() method.
126      *
127      * @var boolean
128      */
129     var $persist = false;
130
131     /**
132      * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server
133      * supports it. This speeds up delivery over high-latency connections. By
134      * default, use the default value supplied by Net_SMTP.
135      * @var bool
136      */
137     var $pipelining;
138
139     /**
140      * Constructor.
141      *
142      * Instantiates a new Mail_smtp:: object based on the parameters
143      * passed in. It looks for the following parameters:
144      *     host        The server to connect to. Defaults to localhost.
145      *     port        The port to connect to. Defaults to 25.
146      *     auth        SMTP authentication.  Defaults to none.
147      *     username    The username to use for SMTP auth. No default.
148      *     password    The password to use for SMTP auth. No default.
149      *     localhost   The local hostname / domain. Defaults to localhost.
150      *     timeout     The SMTP connection timeout. Defaults to none.
151      *     verp        Whether to use VERP or not. Defaults to false.
152      *                 DEPRECATED as of 1.2.0 (use setMailParams()).
153      *     debug       Activate SMTP debug mode? Defaults to false.
154      *     persist     Should the SMTP connection persist?
155      *     pipelining  Use SMTP command pipelining
156      *
157      * If a parameter is present in the $params array, it replaces the
158      * default.
159      *
160      * @param array Hash containing any parameters different from the
161      *              defaults.
162      * @access public
163      */
164     function Mail_smtp($params)
165     {
166         if (isset($params['host'])) $this->host = $params['host'];
167         if (isset($params['port'])) $this->port = $params['port'];
168         if (isset($params['auth'])) $this->auth = $params['auth'];
169         if (isset($params['username'])) $this->username = $params['username'];
170         if (isset($params['password'])) $this->password = $params['password'];
171         if (isset($params['localhost'])) $this->localhost = $params['localhost'];
172         if (isset($params['timeout'])) $this->timeout = $params['timeout'];
173         if (isset($params['debug'])) $this->debug = (bool)$params['debug'];
174         if (isset($params['persist'])) $this->persist = (bool)$params['persist'];
175         if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining'];
176
177         // Deprecated options
178         if (isset($params['verp'])) {
179             $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']);
180         }
181
182         register_shutdown_function(array(&$this, '_Mail_smtp'));
183     }
184
185     /**
186      * Destructor implementation to ensure that we disconnect from any
187      * potentially-alive persistent SMTP connections.
188      */
189     function _Mail_smtp()
190     {
191         $this->disconnect();
192     }
193
194     /**
195      * Implements Mail::send() function using SMTP.
196      *
197      * @param mixed $recipients Either a comma-seperated list of recipients
198      *              (RFC822 compliant), or an array of recipients,
199      *              each RFC822 valid. This may contain recipients not
200      *              specified in the headers, for Bcc:, resending
201      *              messages, etc.
202      *
203      * @param array $headers The array of headers to send with the mail, in an
204      *              associative array, where the array key is the
205      *              header name (e.g., 'Subject'), and the array value
206      *              is the header value (e.g., 'test'). The header
207      *              produced from those values would be 'Subject:
208      *              test'.
209      *
210      * @param string $body The full text of the message body, including any
211      *               MIME parts, etc.
212      *
213      * @return mixed Returns true on success, or a PEAR_Error
214      *               containing a descriptive error message on
215      *               failure.
216      * @access public
217      */
218     function send($recipients, $headers, $body)
219     {
220         /* If we don't already have an SMTP object, create one. */
221         $result = &$this->getSMTPObject();
222         if (PEAR::isError($result)) {
223             return $result;
224         }
225
226         if (!is_array($headers)) {
227             return PEAR::raiseError('$headers must be an array');
228         }
229
230         $this->_sanitizeHeaders($headers);
231
232         $headerElements = $this->prepareHeaders($headers);
233         if (is_a($headerElements, 'PEAR_Error')) {
234             $this->_smtp->rset();
235             return $headerElements;
236         }
237         list($from, $textHeaders) = $headerElements;
238
239         /* Since few MTAs are going to allow this header to be forged
240          * unless it's in the MAIL FROM: exchange, we'll use
241          * Return-Path instead of From: if it's set. */
242         if (!empty($headers['Return-Path'])) {
243             $from = $headers['Return-Path'];
244         }
245
246         if (!isset($from)) {
247             $this->_smtp->rset();
248             return PEAR::raiseError('No From: address has been provided',
249                                     PEAR_MAIL_SMTP_ERROR_FROM);
250         }
251
252         $params = null;
253         if (!empty($this->_extparams)) {
254             foreach ($this->_extparams as $key => $val) {
255                 $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
256             }
257         }
258         if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) {
259             $error = $this->_error("Failed to set sender: $from", $res);
260             $this->_smtp->rset();
261             return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
262         }
263
264         $recipients = $this->parseRecipients($recipients);
265         if (is_a($recipients, 'PEAR_Error')) {
266             $this->_smtp->rset();
267             return $recipients;
268         }
269
270         foreach ($recipients as $recipient) {
271             $res = $this->_smtp->rcptTo($recipient);
272             if (is_a($res, 'PEAR_Error')) {
273                 $error = $this->_error("Failed to add recipient: $recipient", $res);
274                 $this->_smtp->rset();
275                 return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
276             }
277         }
278
279         /* Send the message's headers and the body as SMTP data. */
280         $res = $this->_smtp->data($textHeaders . "\r\n\r\n" . $body);
281         if (is_a($res, 'PEAR_Error')) {
282             $error = $this->_error('Failed to send data', $res);
283             $this->_smtp->rset();
284             return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
285         }
286
287         /* If persistent connections are disabled, destroy our SMTP object. */
288         if ($this->persist === false) {
289             $this->disconnect();
290         }
291
292         return true;
293     }
294
295     /**
296      * Connect to the SMTP server by instantiating a Net_SMTP object.
297      *
298      * @return mixed Returns a reference to the Net_SMTP object on success, or
299      *               a PEAR_Error containing a descriptive error message on
300      *               failure.
301      *
302      * @since  1.2.0
303      * @access public
304      */
305     function &getSMTPObject()
306     {
307         if (is_object($this->_smtp) !== false) {
308             return $this->_smtp;
309         }
310
311         include_once 'Net/SMTP.php';
312         $this->_smtp = &new Net_SMTP($this->host,
313                                      $this->port,
314                                      $this->localhost);
315
316         /* If we still don't have an SMTP object at this point, fail. */
317         if (is_object($this->_smtp) === false) {
318             return PEAR::raiseError('Failed to create a Net_SMTP object',
319                                     PEAR_MAIL_SMTP_ERROR_CREATE);
320         }
321
322         /* Configure the SMTP connection. */
323         if ($this->debug) {
324             $this->_smtp->setDebug(true);
325         }
326
327         /* Attempt to connect to the configured SMTP server. */
328         if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
329             $error = $this->_error('Failed to connect to ' .
330                                    $this->host . ':' . $this->port,
331                                    $res);
332             return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
333         }
334
335         /* Attempt to authenticate if authentication has been enabled. */
336         if ($this->auth) {
337             $method = is_string($this->auth) ? $this->auth : '';
338
339             if (PEAR::isError($res = $this->_smtp->auth($this->username,
340                                                         $this->password,
341                                                         $method))) {
342                 $error = $this->_error("$method authentication failure",
343                                        $res);
344                 $this->_smtp->rset();
345                 return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
346             }
347         }
348
349         return $this->_smtp;
350     }
351
352     /**
353      * Add parameter associated with a SMTP service extension.
354      *
355      * @param string Extension keyword.
356      * @param string Any value the keyword needs.
357      *
358      * @since 1.2.0
359      * @access public
360      */
361     function addServiceExtensionParameter($keyword, $value = null)
362     {
363         $this->_extparams[$keyword] = $value;
364     }
365
366     /**
367      * Disconnect and destroy the current SMTP connection.
368      *
369      * @return boolean True if the SMTP connection no longer exists.
370      *
371      * @since  1.1.9
372      * @access public
373      */
374     function disconnect()
375     {
376         /* If we have an SMTP object, disconnect and destroy it. */
377         if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
378             $this->_smtp = null;
379         }
380
381         /* We are disconnected if we no longer have an SMTP object. */
382         return ($this->_smtp === null);
383     }
384
385     /**
386      * Build a standardized string describing the current SMTP error.
387      *
388      * @param string $text  Custom string describing the error context.
389      * @param object $error Reference to the current PEAR_Error object.
390      *
391      * @return string       A string describing the current SMTP error.
392      *
393      * @since  1.1.7
394      * @access private
395      */
396     function _error($text, &$error)
397     {
398         /* Split the SMTP response into a code and a response string. */
399         list($code, $response) = $this->_smtp->getResponse();
400
401         /* Build our standardized error string. */
402         return $text
403             . ' [SMTP: ' . $error->getMessage()
404             . " (code: $code, response: $response)]";
405     }
406
407 }