[ Index ] |
|
Code source de dotProject 2.1 RC1 |
1 <?php /* CLASSES $Id: libmail.class.php,v 1.14.8.9 2007/01/31 09:36:52 ajdonnison Exp $ */ 2 /** 3 * @package dotproject 4 * @subpackage utilites 5 */ 6 7 if (!defined('DP_BASE_DIR')){ 8 die('You should not access this file directly'); 9 } 10 11 /** 12 * This class encapsulates the PHP mail() function. 13 * 14 * implements CC, Bcc, Priority headers 15 * @version 1.3 16 * <ul> 17 * <li>added ReplyTo( $address ) method 18 * <li>added Receipt() method - to add a mail receipt 19 * <li>added optionnal charset parameter to Body() method. this should fix charset problem on some mail clients 20 * </ul> 21 * Example 22 * <code> 23 * include "libmail.php"; 24 * 25 * $m= new Mail; // create the mail 26 * $m->From( "leo@isp.com" ); 27 * $m->To( "destination@somewhere.fr" ); 28 * $m->Subject( "the subject of the mail" ); 29 * 30 * $message= "Hello world!\nthis is a test of the Mail class\nplease ignore\nThanks."; 31 * $m->Body( $message); // set the body 32 * $m->Cc( "someone@somewhere.fr"); 33 * $m->Bcc( "someoneelse@somewhere.fr"); 34 * $m->Priority(4) ; // set the priority to Low 35 * $m->Attach( "/home/leo/toto.gif", "image/gif" ) ; // attach a file of type image/gif 36 * $m->Send(); // send the mail 37 * echo "the mail below has been sent:<br><pre>", $m->Get(), "</pre>"; 38 * </code> 39 40 LASTMOD 41 Fri Oct 6 15:46:12 UTC 2000 42 43 * @author Leo West - lwest@free.fr 44 */ 45 class Mail 46 { 47 /** 48 * list of To addresses 49 * @var array 50 */ 51 var $sendto = array(); 52 /** 53 * @var array 54 */ 55 var $acc = array(); 56 /** 57 * @var array 58 */ 59 var $abcc = array(); 60 /** 61 * paths of attached files 62 * @var array 63 */ 64 var $aattach = array(); 65 /** 66 * list of message headers 67 * @var array 68 */ 69 var $xheaders = array(); 70 /** 71 * message priorities referential 72 * @var array 73 */ 74 var $priorities = array( '1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)' ); 75 /** 76 * character set of message 77 * @var string 78 */ 79 var $charset = "us-ascii"; 80 var $ctencoding = "7bit"; 81 var $receipt = 0; 82 83 var $useRawAddress = true; 84 85 var $host; 86 var $port; 87 var $sasl; 88 var $username; 89 var $password; 90 var $transport; 91 var $defer; 92 93 /** 94 * Mail constructor 95 */ 96 function Mail() 97 { 98 global $dPconfig; 99 100 $this->autoCheck( true ); 101 $this->boundary= "--" . md5( uniqid("myboundary") ); 102 // Grab the current mail handling options 103 $this->transport = isset($dPconfig['mail_transport']) ? $dPconfig['mail_transport'] : 'php'; 104 $this->host = isset($dPconfig['mail_host']) ? $dPconfig['mail_host'] : 'localhost'; 105 $this->port = isset($dPconfig['mail_port']) ? $dPconfig['mail_port'] : '25'; 106 $this->sasl = isset($dPconfig['mail_auth']) ? $dPconfig['mail_auth'] : false; 107 $this->username = @$dPconfig['mail_user']; 108 $this->password = @$dPconfig['mail_pass']; 109 $this->defer = @$dPconfig['mail_defer']; 110 $this->timeout = isset($dPconfig['mail_timeout']) ? $dPconfig['mail_timeout'] : 0; 111 } 112 113 114 /** 115 * activate or desactivate the email addresses validator 116 * 117 * ex: autoCheck( true ) turn the validator on 118 * by default autoCheck feature is on 119 120 * @param boolean $bool set to true to turn on the auto validation 121 * @access public 122 */ 123 function autoCheck( $bool ) 124 { 125 if( $bool ) { 126 $this->checkAddress = true; 127 } else { 128 $this->checkAddress = false; 129 } 130 } 131 132 133 /** 134 * Define the subject line of the email 135 * @param string $subject any monoline string 136 * @param string $charset encoding to be used for Quoted-Printable encoding of the subject 137 */ 138 function Subject( $subject, $charset='' ) { 139 global $dPconfig; 140 141 if( isset($charset) && $charset != "" ) { 142 $this->charset = strtolower($charset); 143 } 144 145 global $AppUI; 146 147 if ( ( $AppUI->user_locale != 'en' || ( $this->charset && $this->charset != 'us-ascii' && $this->charset != 'utf-8') ) && function_exists('imap_8bit')) { 148 $subject = "=?".$this->charset."?Q?". 149 str_replace("=\r\n","",imap_8bit($subject))."?="; 150 } 151 $this->xheaders['Subject'] = $dPconfig['email_prefix'].' '.strtr( $subject, "\r\n" , " " ); 152 } 153 154 155 /** 156 * set the sender of the mail 157 * @param string $from should be an email address 158 159 */ 160 161 function From( $from ) { 162 if( ! is_string($from) ) { 163 echo "Class Mail: error, From is not a string"; 164 exit; 165 } 166 $this->xheaders['From'] = $from; 167 } 168 169 /** 170 * set the Reply-to header 171 * @param string $email should be an email address 172 */ 173 function ReplyTo( $address ) { 174 if (!is_string($address)) { 175 return false; 176 } 177 $this->xheaders["Reply-To"] = $address; 178 } 179 180 /** 181 * add a receipt to the mail ie. a confirmation is returned to the "From" address (or "ReplyTo" if defined) 182 * when the receiver opens the message. 183 * @warning this functionality is *not* a standard, thus only some mail clients are compliants. 184 */ 185 186 function Receipt() { 187 $this->receipt = 1; 188 } 189 190 /** 191 * set the mail recipient 192 * 193 * The optional reset parameter is useful when looping through records to send individual mails. 194 * This prevents the 'to' array being continually stacked with additional addresses. 195 * 196 * @param string $to email address, accept both a single address or an array of addresses 197 * @param boolean $reset resets the current array 198 */ 199 200 function To( $to, $reset=false ) { 201 202 // TODO : test validit? sur to 203 if( is_array( $to ) ) { 204 $this->sendto = $to; 205 } else { 206 if ($this->useRawAddress) { 207 if( preg_match( "/^(.*)\<(.+)\>$/", $to, $regs ) ) { 208 $to = $regs[2]; 209 } 210 } 211 if ($reset) { 212 unset( $this->sendto ); 213 $this->sendto = array(); 214 } 215 $this->sendto[] = $to; 216 } 217 218 if( $this->checkAddress == true ) 219 $this->CheckAdresses( $this->sendto ); 220 221 } 222 223 224 /** 225 * Cc() 226 * set the CC headers ( carbon copy ) 227 * $cc : email address(es), accept both array and string 228 */ 229 230 function Cc( $cc ) { 231 if( is_array($cc) ) 232 $this->acc= $cc; 233 else 234 $this->acc= explode(',', $cc); 235 236 if( $this->checkAddress == true ) 237 $this->CheckAdresses( $this->acc ); 238 239 } 240 241 /** 242 * set the Bcc headers ( blank carbon copy ). 243 * $bcc : email address(es), accept both array and string 244 */ 245 246 function Bcc( $bcc ) { 247 if( is_array($bcc) ) { 248 $this->abcc = $bcc; 249 } else { 250 $this->abcc[]= $bcc; 251 } 252 253 if( $this->checkAddress == true ) 254 $this->CheckAdresses( $this->abcc ); 255 } 256 257 /** 258 * set the body (message) of the mail 259 * define the charset if the message contains extended characters (accents) 260 * default to us-ascii 261 * $mail->Body( "m?l en fran?ais avec des accents", "iso-8859-1" ); 262 */ 263 function Body( $body, $charset="" ) { 264 $this->body = $body; 265 266 if( isset($charset) && $charset != "" ) { 267 $this->charset = strtolower($charset); 268 if( $this->charset != "us-ascii" ) 269 $this->ctencoding = "8bit"; 270 } 271 } 272 273 /** 274 * set the Organization header 275 */ 276 function Organization( $org ) { 277 if( trim( $org != "" ) ) 278 $this->xheaders['Organization'] = $org; 279 } 280 281 /** 282 * set the mail priority 283 * $priority : integer taken between 1 (highest) and 5 ( lowest ) 284 * ex: $mail->Priority(1) ; => Highest 285 */ 286 287 function Priority( $priority ) { 288 if( ! intval( $priority ) ) 289 return false; 290 291 if( ! isset( $this->priorities[$priority-1]) ) 292 return false; 293 294 $this->xheaders["X-Priority"] = $this->priorities[$priority-1]; 295 296 return true; 297 } 298 299 /** 300 * Attach a file to the mail 301 * 302 * @param string $filename : path of the file to attach 303 * @param string $filetype : MIME-type of the file. default to 'application/x-unknown-content-type' 304 * @param string $disposition : instruct the Mailclient to display the file if possible ("inline") or always as a link ("attachment") possible values are "inline", "attachment" 305 */ 306 function Attach( $filename, $filetype = "", $disposition = "inline" ) { 307 // TODO : si filetype="", alors chercher dans un tablo de MT connus / extension du fichier 308 if( $filetype == "" ) 309 $filetype = "application/x-unknown-content-type"; 310 311 $this->aattach[] = $filename; 312 $this->actype[] = $filetype; 313 $this->adispo[] = $disposition; 314 } 315 316 /** 317 * Build the email message 318 * @access protected 319 */ 320 function BuildMail() { 321 // build the headers 322 global $AppUI; 323 324 $this->headers = ""; 325 // $this->xheaders['To'] = implode( ", ", $this->sendto ); 326 327 if( count($this->acc) > 0 ) { 328 $this->xheaders['CC'] = implode( ", ", $this->acc ); 329 } 330 if( count($this->abcc) > 0 ) { 331 $this->xheaders['BCC'] = implode( ", ", $this->abcc ); 332 } 333 334 if( $this->receipt ) { 335 if( isset($this->xheaders["Reply-To"] ) ) { 336 $this->xheaders["Disposition-Notification-To"] = $this->xheaders["Reply-To"]; 337 } else { 338 $this->xheaders["Disposition-Notification-To"] = $this->xheaders['From']; 339 } 340 } 341 342 if( $this->charset != "" ) { 343 $this->xheaders["Mime-Version"] = "1.0"; 344 $this->xheaders["Content-Type"] = "text/plain; charset=$this->charset"; 345 $this->xheaders["Content-Transfer-Encoding"] = $this->ctencoding; 346 } 347 348 $this->xheaders["X-Mailer"] = "dotProject v" . $AppUI->getVersion(); 349 350 // include attached files 351 if( count( $this->aattach ) > 0 ) { 352 $this->_build_attachement(); 353 } else { 354 $sep = "\n"; 355 $arr = preg_split("/(\r?\n)|\r/", $this->body); 356 $this->fullBody = implode($sep, $arr); 357 } 358 359 reset($this->xheaders); 360 while( list( $hdr,$value ) = each( $this->xheaders ) ) { 361 if( $hdr != "Subject" ) 362 $this->headers .= "$hdr: $value\n"; 363 } 364 } 365 366 /** 367 * format and send the mail 368 * @access public 369 */ 370 function Send() { 371 $this->BuildMail(); 372 373 $this->strTo = implode( ", ", $this->sendto ); 374 375 if ($this->defer) 376 return $this->QueueMail(); 377 else if ($this->transport == 'smtp') 378 return $this->SMTPSend( $this->sendto, $this->xheaders['Subject'], $this->fullBody, $this->xheaders ); 379 else 380 return @mail( $this->strTo, $this->xheaders['Subject'], $this->fullBody, $this->headers ); 381 } 382 383 /** 384 * Send email via an SMTP connection. 385 * 386 * Work based loosly on that of Bugs Genie, which appears to be in turn based on something from 'Ninebirds' 387 * 388 * @access public 389 */ 390 function SMTPSend($to, $subject, $body, &$headers) { 391 global $AppUI, $dPconfig; 392 393 // Start the connection to the server 394 $error_number = 0; 395 $error_message = ''; 396 $this->socket = fsockopen($this->host, $this->port, $error_number, $error_message, $this->timeout); 397 if (! $this->socket) { 398 dprint(__FILE__, __LINE__, 1, "Error on connecting to host {$this->host} at port {$this->port}: $error_message ($error_number)"); 399 $AppUI->setMsg("Cannot connect to SMTP Host: $error_message ($error_number)"); 400 return false; 401 } 402 // Read the opening stuff; 403 $this->socketRead(); 404 // Send the protocol start 405 $this->socketSend("HELO " . $this->getHostName()); 406 if ($this->sasl && $this->username) { 407 $this->socketSend("AUTH LOGIN"); 408 $this->socketSend(base64_encode($this->username)); 409 $rcv = $this->socketSend(base64_encode($this->password)); 410 if (strpos($rcv, '235') !== 0) { 411 dprint(__FILE__, __LINE__, 1, "Authentication failed on server: $rcv"); 412 $AppUI->setMsg("Failed to login to SMTP server: $rcv"); 413 fclose($this->socket); 414 return false; 415 } 416 } 417 // Determine the mail from address. 418 if ( ! isset($headers['From'])) { 419 $from = $dPconfig['admin_user'] . '@' . $dPconfig['site_domain']; 420 } else { 421 // Search for the parts of the email address 422 if (preg_match('/.*<([^@]+@[a-z0-9\._-]+)>/i', $headers['From'], $matches)) 423 $from = $matches[1]; 424 else 425 $from = $headers['From']; 426 } 427 $rcv = $this->socketSend("MAIL FROM: <$from>"); 428 if (substr($rcv,0,1) != '2') { 429 $AppUI->setMsg("Failed to send email: $rcv", UI_MSG_ERROR); 430 return false; 431 } 432 foreach ($to as $to_address) { 433 if (strpos($to_address, '<') !== false) { 434 preg_match('/^.*<([^@]+\@[a-z0-9\._-]+)>/i', $to_address, $matches); 435 if (isset($matches[1])) 436 $to_address = $matches[1]; 437 } 438 $rcv = $this->socketSend("RCPT TO: <$to_address>"); 439 if (substr($rcv,0,1) != '2') { 440 $AppUI->setMsg("Failed to send email: $rcv", UI_MSG_ERROR); 441 return false; 442 } 443 } 444 $this->socketSend("DATA"); 445 foreach ($headers as $hdr =>$val) { 446 $this->socketSend("$hdr: $val", false); 447 } 448 // Now build the To Headers as well. 449 $this->socketSend("To: " . implode(', ', $to), false); 450 $this->socketSend("Date: " . date('r'), false); 451 $this->socketSend("", false); 452 $this->socketSend($body, false); 453 $result = $this->socketSend(".\r\nQUIT"); 454 if (strpos($result, '250') === 0) 455 return true; 456 else { 457 dprint(__FILE__, __LINE__, 1, "Failed to send email from $from to $to_address: $result"); 458 $AppUI->setMsg("Failed to send email: $result"); 459 return false; 460 } 461 } 462 463 function socketRead() 464 { 465 $result = fgets($this->socket, 4096); 466 dprint(__FILE__, __LINE__, 12, "server said: $result"); 467 return $result; 468 } 469 470 function socketSend($msg, $rcv = true) 471 { 472 dprint(__FILE__, __LINE__, 12, "sending: $msg"); 473 $sent = fputs($this->socket, $msg . "\r\n"); 474 if ($rcv) 475 return $this->socketRead(); 476 else 477 return $sent; 478 } 479 480 function getHostName() 481 { 482 // Grab the server address, return a hostname for it. 483 if ($host = gethostbyaddr($_SERVER['SERVER_ADDR'])) 484 return $host; 485 else 486 return '[' . $_SERVER['SERVER_ADDR'] . ']'; 487 } 488 489 /** 490 * Queue mail to allow the queue manager to trigger 491 * the email transfer. 492 * 493 * @access private 494 */ 495 function QueueMail() { 496 global $AppUI; 497 498 require_once $AppUI->getSystemClass('event_queue'); 499 $ec = new EventQueue; 500 $vars = get_object_vars($this); 501 return $ec->add(array('Mail', 'SendQueuedMail'), $vars, 'libmail', true); 502 } 503 504 /** 505 * Dequeue the email and transfer it. Called from the queue manager. 506 * 507 * @access private 508 */ 509 function SendQueuedMail($mod, $type, $originator, $owner, &$args) { 510 extract($args); 511 if ($this->transport == 'smtp') { 512 return $this->SMTPSend($sendto, $xheaders['Subject'], $fullBody, $xheaders); 513 } else { 514 return @mail( $strTo, $xheaders['Subject'], $fullBody, $headers ); 515 } 516 } 517 518 /** 519 * Returns the whole e-mail , headers + message 520 * 521 * can be used for displaying the message in plain text or logging it 522 * 523 * @return string 524 */ 525 function Get() { 526 $this->BuildMail(); 527 $mail = "To: " . $this->strTo . "\r\n"; 528 $mail .= $this->headers . "\r\n"; 529 $mail .= $this->fullBody; 530 return $mail; 531 } 532 533 /** 534 * check an email address validity 535 * @access public 536 * @param string $address : email address to check 537 * @return true if email adress is ok 538 */ 539 function ValidEmail($address) { 540 if( preg_match( "/^(.*)\<(.+)\>$/", $address, $regs ) ) { 541 $address = $regs[2]; 542 } 543 if( preg_match( "/^[^@ ]+@([a-zA-Z0-9.\-.]+)$/",$address) ) { 544 return true; 545 } else { 546 return false; 547 } 548 } 549 550 /** 551 * check validity of email addresses 552 * @param array $aad - 553 * @return if unvalid, output an error message and exit, this may -should- be customized 554 */ 555 556 function CheckAdresses( $aad ) { 557 for($i=0;$i< count( $aad); $i++ ) { 558 if( ! $this->ValidEmail( $aad[$i]) ) { 559 echo "Class Mail, method Mail : invalid address $aad[$i]"; 560 exit; 561 } 562 } 563 return true; 564 } 565 /** 566 * alias for the mispelled CheckAdresses 567 */ 568 function CheckAddresses($aad) { 569 return $this->CheckAdresses($aad); 570 } 571 572 /** 573 * check and encode attach file(s) . internal use only 574 * @access private 575 */ 576 function _build_attachement() { 577 $this->xheaders["Content-Type"] = "multipart/mixed;\r\n boundary=\"$this->boundary\""; 578 579 $this->fullBody = "This is a multi-part message in MIME format.\r\n--$this->boundary\r\n"; 580 $this->fullBody .= "Content-Type: text/plain; charset=$this->charset\r\nContent-Transfer-Encoding: $this->ctencoding\r\n\r\n"; 581 582 $sep= "\r\n"; 583 $body = preg_split("/\r?\n/", $this->body); 584 $this->fullBody .= implode($sep, $body) ."\r\n"; 585 586 $ata= array(); 587 $k=0; 588 589 // for each attached file, do... 590 for( $i=0; $i < count( $this->aattach); $i++ ) { 591 $filename = $this->aattach[$i]; 592 $basename = basename($filename); 593 $ctype = $this->actype[$i]; // content-type 594 $disposition = $this->adispo[$i]; 595 596 if( ! file_exists( $filename) ) { 597 echo "Class Mail, method attach : file $filename can't be found"; exit; 598 } 599 $subhdr= "--$this->boundary\r\nContent-type: $ctype;\r\n name=\"$basename\"\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: $disposition;\r\n filename=\"$basename\"\r\n"; 600 $ata[$k++] = $subhdr; 601 // non encoded line length 602 $linesz= filesize( $filename)+1; 603 $fp= fopen( $filename, 'r' ); 604 $ata[$k++] = chunk_split(base64_encode(fread( $fp, $linesz))); 605 fclose($fp); 606 } 607 $this->fullBody .= implode($sep, $ata); 608 } 609 610 } // class Mail 611 612 613 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 18 19:46:52 2007 | par Balluche grâce à PHPXref 0.7 |