3 // +----------------------------------------------------------------------+
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 // +----------------------------------------------------------------------+
20 /** Error: Failed to create a Net_SMTP object */
21 define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
23 /** Error: Failed to connect to SMTP server */
24 define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
26 /** Error: SMTP authentication failure */
27 define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
29 /** Error: No From: address has been provided */
30 define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
32 /** Error: Failed to set sender */
33 define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
35 /** Error: Failed to add recipient */
36 define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
38 /** Error: Failed to send data */
39 define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);
42 * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
45 * @version $Revision: 1.28 $
47 class Mail_smtp
extends Mail
{
50 * SMTP connection object.
58 * The SMTP host to connect to.
61 var $host = 'localhost';
64 * The port the SMTP server is on.
70 * Should SMTP authentication be used?
72 * This value may be set to true, false or the name of a specific
73 * authentication method.
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.
83 * The username to use if the SMTP server requires authentication.
89 * The password to use if the SMTP server requires authentication.
95 * Hostname or domain that will be sent to the remote SMTP server in the
96 * HELO / EHLO message.
100 var $localhost = 'localhost';
103 * SMTP connection timeout value. NULL indicates no timeout.
110 * Whether to use VERP or not. If not a boolean, the string value
111 * will be used as the VERP separators.
113 * @var mixed boolean or string
118 * Turn on Net_SMTP debugging?
120 * @var boolean $debug
125 * Indicates whether or not the SMTP connection should persist over
126 * multiple calls to the send() method.
130 var $persist = false
;
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?
148 * If a parameter is present in the $params array, it replaces the
151 * @param array Hash containing any parameters different from the
155 function Mail_smtp($params)
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'];
168 register_shutdown_function(array(&$this, '_Mail_smtp'));
172 * Destructor implementation to ensure that we disconnect from any
173 * potentially-alive persistent SMTP connections.
175 function _Mail_smtp()
181 * Implements Mail::send() function using SMTP.
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
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:
196 * @param string $body The full text of the message body, including any
199 * @return mixed Returns true on success, or a PEAR_Error
200 * containing a descriptive error message on
204 function send($recipients, $headers, $body)
206 include_once 'Net/SMTP.php';
208 /* If we don't already have an SMTP object, create one. */
209 if (is_object($this->_smtp
) === false
) {
210 $this->_smtp
= new Net_SMTP($this->host
, $this->port
,
213 /* If we still don't have an SMTP object at this point, fail. */
214 if (is_object($this->_smtp
) === false
) {
215 return PEAR
::raiseError('Failed to create a Net_SMTP object',
216 PEAR_MAIL_SMTP_ERROR_CREATE
);
219 /* Configure the SMTP connection. */
221 $this->_smtp
->setDebug(true
);
224 /* Attempt to connect to the configured SMTP server. */
225 if (PEAR
::isError($res = $this->_smtp
->connect($this->timeout
))) {
226 $error = $this->_error('Failed to connect to ' .
227 $this->host
. ':' . $this->port
,
229 return PEAR
::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT
);
232 /* Attempt to authenticate if authentication has been enabled. */
234 $method = is_string($this->auth
) ?
$this->auth
: '';
236 if (PEAR
::isError($res = $this->_smtp
->auth($this->username
,
239 $error = $this->_error("$method authentication failure",
241 $this->_smtp
->rset();
242 return PEAR
::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH
);
247 $this->_sanitizeHeaders($headers);
248 $headerElements = $this->prepareHeaders($headers);
249 if (PEAR
::isError($headerElements)) {
250 $this->_smtp
->rset();
251 return $headerElements;
253 list($from, $textHeaders) = $headerElements;
255 /* Since few MTAs are going to allow this header to be forged
256 * unless it's in the MAIL FROM: exchange, we'll use
257 * Return-Path instead of From: if it's set. */
258 if (!empty($headers['Return-Path'])) {
259 $from = $headers['Return-Path'];
263 $this->_smtp
->rset();
264 return PEAR
::raiseError('No From: address has been provided',
265 PEAR_MAIL_SMTP_ERROR_FROM
);
268 $args['verp'] = $this->verp
;
269 if (PEAR
::isError($res = $this->_smtp
->mailFrom($from, $args))) {
270 $error = $this->_error("Failed to set sender: $from", $res);
271 $this->_smtp
->rset();
272 return PEAR
::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER
);
275 $recipients = $this->parseRecipients($recipients);
276 if (PEAR
::isError($recipients)) {
277 $this->_smtp
->rset();
281 foreach ($recipients as $recipient) {
282 if (PEAR
::isError($res = $this->_smtp
->rcptTo($recipient))) {
283 $error = $this->_error("Failed to add recipient: $recipient",
285 $this->_smtp
->rset();
286 return PEAR
::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT
);
290 /* Send the message's headers and the body as SMTP data. */
291 if (PEAR
::isError($res = $this->_smtp
->data($textHeaders . "\r\n\r\n" . $body))) {
292 $error = $this->_error('Failed to send data', $res);
293 $this->_smtp
->rset();
294 return PEAR
::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA
);
297 /* If persistent connections are disabled, destroy our SMTP object. */
298 if ($this->persist
=== false
) {
306 * Disconnect and destroy the current SMTP connection.
308 * @return boolean True if the SMTP connection no longer exists.
313 function disconnect()
315 /* If we have an SMTP object, disconnect and destroy it. */
316 if (is_object($this->_smtp
) && $this->_smtp
->disconnect()) {
320 /* We are disconnected if we no longer have an SMTP object. */
321 return ($this->_smtp
=== null
);
325 * Build a standardized string describing the current SMTP error.
327 * @param string $text Custom string describing the error context.
328 * @param object $error Reference to the current PEAR_Error object.
330 * @return string A string describing the current SMTP error.
335 function _error($text, &$error)
337 /* Split the SMTP response into a code and a response string. */
338 list($code, $response) = $this->_smtp
->getResponse();
340 /* Build our standardized error string. */
342 $msg .= ' [SMTP: ' . $error->getMessage();
343 $msg .= " (code: $code, response: $response)]";