ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
smtpmx.php
Go to the documentation of this file.
1<?PHP
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
50require_once 'Net/SMTP.php';
51
61class Mail_smtpmx extends Mail {
62
69 var $_smtp = null;
70
76 var $port = 25;
77
85 var $mailname = 'localhost';
86
92 var $timeout = 10;
93
99 var $withNetDns = true;
100
107
114 var $verp = false;
115
121 var $vrfy = false;
122
128 var $test = false;
129
135 var $debug = false;
136
149 var $errorCode = array(
150 'not_connected' => array(
151 'code' => 1,
152 'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
153 ),
154 'failed_vrfy_rcpt' => array(
155 'code' => 2,
156 'msg' => 'Recipient "{RCPT}" could not be veryfied.'
157 ),
158 'failed_set_from' => array(
159 'code' => 3,
160 'msg' => 'Failed to set sender: {FROM}.'
161 ),
162 'failed_set_rcpt' => array(
163 'code' => 4,
164 'msg' => 'Failed to set recipient: {RCPT}.'
165 ),
166 'failed_send_data' => array(
167 'code' => 5,
168 'msg' => 'Failed to send mail to: {RCPT}.'
169 ),
170 'no_from' => array(
171 'code' => 5,
172 'msg' => 'No from address has be provided.'
173 ),
174 'send_data' => array(
175 'code' => 7,
176 'msg' => 'Failed to create Net_SMTP object.'
177 ),
178 'no_mx' => array(
179 'code' => 8,
180 'msg' => 'No MX-record for {RCPT} found.'
181 ),
182 'no_resolver' => array(
183 'code' => 9,
184 'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
185 ),
186 'failed_rset' => array(
187 'code' => 10,
188 'msg' => 'RSET command failed, SMTP-connection corrupt.'
189 ),
190 );
191
215 {
216 if (isset($params['mailname'])) {
217 $this->mailname = $params['mailname'];
218 } else {
219 // try to find a valid mailname
220 if (function_exists('posix_uname')) {
221 $uname = posix_uname();
222 $this->mailname = $uname['nodename'];
223 }
224 }
225
226 // port number
227 if (isset($params['port'])) {
228 $this->_port = $params['port'];
229 } else {
230 $this->_port = getservbyname('smtp', 'tcp');
231 }
232
233 if (isset($params['timeout'])) $this->timeout = $params['timeout'];
234 if (isset($params['verp'])) $this->verp = $params['verp'];
235 if (isset($params['test'])) $this->test = $params['test'];
236 if (isset($params['peardebug'])) $this->test = $params['peardebug'];
237 if (isset($params['netdns'])) $this->withNetDns = $params['netdns'];
238 }
239
248 {
249 $this->__construct($params);
250 register_shutdown_function(array(&$this, '__destruct'));
251 }
252
257 function __destruct()
258 {
259 if (is_object($this->_smtp)) {
260 $this->_smtp->disconnect();
261 $this->_smtp = null;
262 }
263 }
264
274 function send($recipients, $headers, $body)
275 {
276 if (!is_array($headers)) {
277 return PEAR::raiseError('$headers must be an array');
278 }
279
280 $result = $this->_sanitizeHeaders($headers);
281 if (is_a($result, 'PEAR_Error')) {
282 return $result;
283 }
284
285 // Prepare headers
286 $headerElements = $this->prepareHeaders($headers);
287 if (is_a($headerElements, 'PEAR_Error')) {
288 return $headerElements;
289 }
290 list($from, $textHeaders) = $headerElements;
291
292 // use 'Return-Path' if possible
293 if (!empty($headers['Return-Path'])) {
294 $from = $headers['Return-Path'];
295 }
296 if (!isset($from)) {
297 return $this->_raiseError('no_from');
298 }
299
300 // Prepare recipients
301 $recipients = $this->parseRecipients($recipients);
302 if (is_a($recipients, 'PEAR_Error')) {
303 return $recipients;
304 }
305
306 foreach ($recipients as $rcpt) {
307 list($user, $host) = explode('@', $rcpt);
308
309 $mx = $this->_getMx($host);
310 if (is_a($mx, 'PEAR_Error')) {
311 return $mx;
312 }
313
314 if (empty($mx)) {
315 $info = array('rcpt' => $rcpt);
316 return $this->_raiseError('no_mx', $info);
317 }
318
319 $connected = false;
320 foreach ($mx as $mserver => $mpriority) {
321 $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname);
322
323 // configure the SMTP connection.
324 if ($this->debug) {
325 $this->_smtp->setDebug(true);
326 }
327
328 // attempt to connect to the configured SMTP server.
329 $res = $this->_smtp->connect($this->timeout);
330 if (is_a($res, 'PEAR_Error')) {
331 $this->_smtp = null;
332 continue;
333 }
334
335 // connection established
336 if ($res) {
337 $connected = true;
338 break;
339 }
340 }
341
342 if (!$connected) {
343 $info = array(
344 'host' => implode(', ', array_keys($mx)),
345 'port' => $this->port,
346 'rcpt' => $rcpt,
347 );
348 return $this->_raiseError('not_connected', $info);
349 }
350
351 // Verify recipient
352 if ($this->vrfy) {
353 $res = $this->_smtp->vrfy($rcpt);
354 if (is_a($res, 'PEAR_Error')) {
355 $info = array('rcpt' => $rcpt);
356 return $this->_raiseError('failed_vrfy_rcpt', $info);
357 }
358 }
359
360 // mail from:
361 $args['verp'] = $this->verp;
362 $res = $this->_smtp->mailFrom($from, $args);
363 if (is_a($res, 'PEAR_Error')) {
364 $info = array('from' => $from);
365 return $this->_raiseError('failed_set_from', $info);
366 }
367
368 // rcpt to:
369 $res = $this->_smtp->rcptTo($rcpt);
370 if (is_a($res, 'PEAR_Error')) {
371 $info = array('rcpt' => $rcpt);
372 return $this->_raiseError('failed_set_rcpt', $info);
373 }
374
375 // Don't send anything in test mode
376 if ($this->test) {
377 $result = $this->_smtp->rset();
378 $res = $this->_smtp->rset();
379 if (is_a($res, 'PEAR_Error')) {
380 return $this->_raiseError('failed_rset');
381 }
382
383 $this->_smtp->disconnect();
384 $this->_smtp = null;
385 return true;
386 }
387
388 // Send data
389 $res = $this->_smtp->data("$textHeaders\r\n$body");
390 if (is_a($res, 'PEAR_Error')) {
391 $info = array('rcpt' => $rcpt);
392 return $this->_raiseError('failed_send_data', $info);
393 }
394
395 $this->_smtp->disconnect();
396 $this->_smtp = null;
397 }
398
399 return true;
400 }
401
411 function _getMx($host)
412 {
413 $mx = array();
414
415 if ($this->withNetDns) {
416 $res = $this->_loadNetDns();
417 if (is_a($res, 'PEAR_Error')) {
418 return $res;
419 }
420
421 $response = $this->resolver->query($host, 'MX');
422 if (!$response) {
423 return false;
424 }
425
426 foreach ($response->answer as $rr) {
427 if ($rr->type == 'MX') {
428 $mx[$rr->exchange] = $rr->preference;
429 }
430 }
431 } else {
432 $mxHost = array();
433 $mxWeight = array();
434
435 if (!getmxrr($host, $mxHost, $mxWeight)) {
436 return false;
437 }
438 for ($i = 0; $i < count($mxHost); ++$i) {
439 $mx[$mxHost[$i]] = $mxWeight[$i];
440 }
441 }
442
443 asort($mx);
444 return $mx;
445 }
446
453 function _loadNetDns()
454 {
455 if (is_object($this->resolver)) {
456 return true;
457 }
458
459 if (!include_once 'Net/DNS.php') {
460 return $this->_raiseError('no_resolver');
461 }
462
463 $this->resolver = new Net_DNS_Resolver();
464 if ($this->debug) {
465 $this->resolver->test = 1;
466 }
467
468 return true;
469 }
470
481 function _raiseError($id, $info = array())
482 {
483 $code = $this->errorCode[$id]['code'];
484 $msg = $this->errorCode[$id]['msg'];
485
486 // include info to messages
487 if (!empty($info)) {
488 $search = array();
489 $replace = array();
490
491 foreach ($info as $key => $value) {
492 array_push($search, '{' . strtoupper($key) . '}');
493 array_push($replace, $value);
494 }
495
496 $msg = str_replace($search, $replace, $msg);
497 }
498
499 return PEAR::raiseError($msg, $code);
500 }
501
502}
$result
SMTP MX.
_raiseError($id, $info=array())
raise standardized error
Definition: smtpmx.php:481
$vrfy
Whether to use VRFY or not.
Definition: smtpmx.php:121
_loadNetDns()
initialize PEAR:Net_DNS_Resolver
Definition: smtpmx.php:453
Mail_smtpmx($params)
Constructor wrapper for PHP4.
Definition: smtpmx.php:247
__construct($params)
Constructor.
Definition: smtpmx.php:214
__destruct()
Destructor implementation to ensure that we disconnect from any potentially-alive persistent SMTP con...
Definition: smtpmx.php:257
_getMx($host)
Recieve mx rexords for a spciefied host.
Definition: smtpmx.php:411
send($recipients, $headers, $body)
Implements Mail::send() function using SMTP direct delivery.
Definition: smtpmx.php:274
$debug
Switch to test mode - don't send emails for real.
Definition: smtpmx.php:135
_sanitizeHeaders(&$headers)
Sanitize an array of mail headers by removing any additional header strings present in a legitimate h...
Definition: Mail.php:153
parseRecipients($recipients)
Take a set of recipients and parse them, returning an array of bare addresses (forward paths) that ca...
Definition: Mail.php:240
prepareHeaders($headers)
Take an array of mail headers and return a string containing text usable in sending a message.
Definition: Mail.php:178
& raiseError($message=null, $code=null, $mode=null, $options=null, $userinfo=null, $error_class=null, $skipmsg=false)
This method is a wrapper that returns an instance of the configured error class with this object's de...
Definition: PEAR.php:524
$params
Definition: example_049.php:96
$code
Definition: example_050.php:99
$info
Definition: example_052.php:80
PEAR's Mail:: interface.