source: branches/beta/data/module/Mail/smtp.php @ 14676

Revision 14676, 12.2 KB checked in by adati, 17 years ago (diff)

1.4.0a-betaのマージ

Line 
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 */
21define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
22
23/** Error: Failed to connect to SMTP server */
24define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
25
26/** Error: SMTP authentication failure */
27define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
28
29/** Error: No From: address has been provided */
30define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
31
32/** Error: Failed to set sender */
33define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
34
35/** Error: Failed to add recipient */
36define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
37
38/** Error: Failed to send data */
39define('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.28 $
46 */
47class 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 SMTP host to connect to.
59     * @var string
60     */
61    var $host = 'localhost';
62
63    /**
64     * The port the SMTP server is on.
65     * @var integer
66     */
67    var $port = 25;
68
69    /**
70     * Should SMTP authentication be used?
71     *
72     * This value may be set to true, false or the name of a specific
73     * authentication method.
74     *
75     * If the value is set to true, the Net_SMTP package will attempt to use
76     * the best authentication method advertised by the remote SMTP server.
77     *
78     * @var mixed
79     */
80    var $auth = false;
81
82    /**
83     * The username to use if the SMTP server requires authentication.
84     * @var string
85     */
86    var $username = '';
87
88    /**
89     * The password to use if the SMTP server requires authentication.
90     * @var string
91     */
92    var $password = '';
93
94    /**
95     * Hostname or domain that will be sent to the remote SMTP server in the
96     * HELO / EHLO message.
97     *
98     * @var string
99     */
100    var $localhost = 'localhost';
101
102    /**
103     * SMTP connection timeout value.  NULL indicates no timeout.
104     *
105     * @var integer
106     */
107    var $timeout = null;
108
109    /**
110     * Whether to use VERP or not. If not a boolean, the string value
111     * will be used as the VERP separators.
112     *
113     * @var mixed boolean or string
114     */
115    var $verp = false;
116
117    /**
118     * Turn on Net_SMTP debugging?
119     *
120     * @var boolean $debug
121     */
122    var $debug = false;
123
124    /**
125     * Indicates whether or not the SMTP connection should persist over
126     * multiple calls to the send() method.
127     *
128     * @var boolean
129     */
130    var $persist = false;
131
132    /**
133     * Constructor.
134     *
135     * Instantiates a new Mail_smtp:: object based on the parameters
136     * passed in. It looks for the following parameters:
137     *     host        The server to connect to. Defaults to localhost.
138     *     port        The port to connect to. Defaults to 25.
139     *     auth        SMTP authentication.  Defaults to none.
140     *     username    The username to use for SMTP auth. No default.
141     *     password    The password to use for SMTP auth. No default.
142     *     localhost   The local hostname / domain. Defaults to localhost.
143     *     timeout     The SMTP connection timeout. Defaults to none.
144     *     verp        Whether to use VERP or not. Defaults to false.
145     *     debug       Activate SMTP debug mode? Defaults to false.
146     *     persist     Should the SMTP connection persist?
147     *
148     * If a parameter is present in the $params array, it replaces the
149     * default.
150     *
151     * @param array Hash containing any parameters different from the
152     *              defaults.
153     * @access public
154     */
155    function Mail_smtp($params)
156    {
157        if (isset($params['host'])) $this->host = $params['host'];
158        if (isset($params['port'])) $this->port = $params['port'];
159        if (isset($params['auth'])) $this->auth = $params['auth'];
160        if (isset($params['username'])) $this->username = $params['username'];
161        if (isset($params['password'])) $this->password = $params['password'];
162        if (isset($params['localhost'])) $this->localhost = $params['localhost'];
163        if (isset($params['timeout'])) $this->timeout = $params['timeout'];
164        if (isset($params['verp'])) $this->verp = $params['verp'];
165        if (isset($params['debug'])) $this->debug = (boolean)$params['debug'];
166        if (isset($params['persist'])) $this->persist = (boolean)$params['persist'];
167
168        register_shutdown_function(array(&$this, '_Mail_smtp'));
169    }
170
171    /**
172     * Destructor implementation to ensure that we disconnect from any
173     * potentially-alive persistent SMTP connections.
174     */
175    function _Mail_smtp()
176    {
177        $this->disconnect();
178    }
179
180    /**
181     * Implements Mail::send() function using SMTP.
182     *
183     * @param mixed $recipients Either a comma-seperated list of recipients
184     *              (RFC822 compliant), or an array of recipients,
185     *              each RFC822 valid. This may contain recipients not
186     *              specified in the headers, for Bcc:, resending
187     *              messages, etc.
188     *
189     * @param array $headers The array of headers to send with the mail, in an
190     *              associative array, where the array key is the
191     *              header name (e.g., 'Subject'), and the array value
192     *              is the header value (e.g., 'test'). The header
193     *              produced from those values would be 'Subject:
194     *              test'.
195     *
196     * @param string $body The full text of the message body, including any
197     *               Mime parts, etc.
198     *
199     * @return mixed Returns true on success, or a PEAR_Error
200     *               containing a descriptive error message on
201     *               failure.
202     * @access public
203     */
204    function send($recipients, $headers, $body)
205    {
206        $include_dir = realpath(dirname( __FILE__));
207        include_once $include_dir . "/../Net/SMTP.php";
208
209        /* If we don't already have an SMTP object, create one. */
210        if (is_object($this->_smtp) === false) {
211            $this->_smtp =& new Net_SMTP($this->host, $this->port,
212                                         $this->localhost);
213
214            /* If we still don't have an SMTP object at this point, fail. */
215            if (is_object($this->_smtp) === false) {
216                return PEAR::raiseError('Failed to create a Net_SMTP object',
217                                        PEAR_MAIL_SMTP_ERROR_CREATE);
218            }
219
220            /* Configure the SMTP connection. */
221            if ($this->debug) {
222                $this->_smtp->setDebug(true);
223            }
224
225            /* Attempt to connect to the configured SMTP server. */
226            if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
227                $error = $this->_error('Failed to connect to ' .
228                                       $this->host . ':' . $this->port,
229                                       $res);
230                return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
231            }
232
233            /* Attempt to authenticate if authentication has been enabled. */
234            if ($this->auth) {
235                $method = is_string($this->auth) ? $this->auth : '';
236
237                if (PEAR::isError($res = $this->_smtp->auth($this->username,
238                                                            $this->password,
239                                                            $method))) {
240                    $error = $this->_error("$method authentication failure",
241                                           $res);
242                    $this->_smtp->rset();
243                    return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
244                }
245            }
246        }
247
248        $this->_sanitizeHeaders($headers);
249        $headerElements = $this->prepareHeaders($headers);
250        if (PEAR::isError($headerElements)) {
251            $this->_smtp->rset();
252            return $headerElements;
253        }
254        list($from, $textHeaders) = $headerElements;
255
256        /* Since few MTAs are going to allow this header to be forged
257         * unless it's in the MAIL FROM: exchange, we'll use
258         * Return-Path instead of From: if it's set. */
259        if (!empty($headers['Return-Path'])) {
260            $from = $headers['Return-Path'];
261        }
262
263        if (!isset($from)) {
264            $this->_smtp->rset();
265            return PEAR::raiseError('No From: address has been provided',
266                                    PEAR_MAIL_SMTP_ERROR_FROM);
267        }
268
269        $args['verp'] = $this->verp;
270        if (PEAR::isError($res = $this->_smtp->mailFrom($from, $args))) {
271            $error = $this->_error("Failed to set sender: $from", $res);
272            $this->_smtp->rset();
273            return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
274        }
275
276        $recipients = $this->parseRecipients($recipients);
277        if (PEAR::isError($recipients)) {
278            $this->_smtp->rset();
279            return $recipients;
280        }
281
282        foreach ($recipients as $recipient) {
283            if (PEAR::isError($res = $this->_smtp->rcptTo($recipient))) {
284                $error = $this->_error("Failed to add recipient: $recipient",
285                                       $res);
286                $this->_smtp->rset();
287                return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
288            }
289        }
290
291        /* Send the message's headers and the body as SMTP data. */
292        if (PEAR::isError($res = $this->_smtp->data($textHeaders . "\r\n\r\n" . $body))) {
293            $error = $this->_error('Failed to send data', $res);
294            $this->_smtp->rset();
295            return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
296        }
297
298        /* If persistent connections are disabled, destroy our SMTP object. */
299        if ($this->persist === false) {
300            $this->disconnect();
301        }
302
303        return true;
304    }
305
306    /**
307     * Disconnect and destroy the current SMTP connection.
308     *
309     * @return boolean True if the SMTP connection no longer exists.
310     *
311     * @since  1.1.9
312     * @access public
313     */
314    function disconnect()
315    {
316        /* If we have an SMTP object, disconnect and destroy it. */
317        if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
318            $this->_smtp = null;
319        }
320
321        /* We are disconnected if we no longer have an SMTP object. */
322        return ($this->_smtp === null);
323    }
324
325    /**
326     * Build a standardized string describing the current SMTP error.
327     *
328     * @param string $text  Custom string describing the error context.
329     * @param object $error Reference to the current PEAR_Error object.
330     *
331     * @return string       A string describing the current SMTP error.
332     *
333     * @since  1.1.7
334     * @access private
335     */
336    function _error($text, &$error)
337    {
338        /* Split the SMTP response into a code and a response string. */
339        list($code, $response) = $this->_smtp->getResponse();
340
341        /* Build our standardized error string. */
342        $msg = $text;
343        $msg .= ' [SMTP: ' . $error->getMessage();
344        $msg .= " (code: $code, response: $response)]";
345
346        return $msg;
347    }
348
349}
Note: See TracBrowser for help on using the repository browser.