[ Index ] |
|
Code source de SPIP Agora 1.4 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 // +-----------------------------------------------------------------------+ 4 // | Copyright (c) 2002-2003 Richard Heyes | 5 // | Copyright (c) 2003-2005 The PHP Group | 6 // | All rights reserved. | 7 // | | 8 // | Redistribution and use in source and binary forms, with or without | 9 // | modification, are permitted provided that the following conditions | 10 // | are met: | 11 // | | 12 // | o Redistributions of source code must retain the above copyright | 13 // | notice, this list of conditions and the following disclaimer. | 14 // | o Redistributions in binary form must reproduce the above copyright | 15 // | notice, this list of conditions and the following disclaimer in the | 16 // | documentation and/or other materials provided with the distribution.| 17 // | o The names of the authors may not be used to endorse or promote | 18 // | products derived from this software without specific prior written | 19 // | permission. | 20 // | | 21 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 22 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 23 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 24 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 25 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 26 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 27 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 28 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 29 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 30 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 31 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 32 // | | 33 // +-----------------------------------------------------------------------+ 34 // | Author: Richard Heyes <richard@phpguru.org> | 35 // | Tomas V.V.Cox <cox@idecnet.com> (port to PEAR) | 36 // +-----------------------------------------------------------------------+ 37 // 38 // $Id: mime.php,v 1.39 2005/06/13 21:24:16 cipri Exp $ 39 40 require_once('PEAR.php'); 41 require_once('Mail/mimePart.php'); 42 43 /** 44 * Mime mail composer class. Can handle: text and html bodies, embedded html 45 * images and attachments. 46 * Documentation and examples of this class are avaible here: 47 * http://pear.php.net/manual/ 48 * 49 * @notes This class is based on HTML Mime Mail class from 50 * Richard Heyes <richard@phpguru.org> which was based also 51 * in the mime_mail.class by Tobias Ratschiller <tobias@dnet.it> and 52 * Sascha Schumann <sascha@schumann.cx> 53 * 54 * @author Richard Heyes <richard.heyes@heyes-computing.net> 55 * @author Tomas V.V.Cox <cox@idecnet.com> 56 * @package Mail 57 * @access public 58 */ 59 class Mail_mime 60 { 61 /** 62 * Contains the plain text part of the email 63 * @var string 64 */ 65 var $_txtbody; 66 /** 67 * Contains the html part of the email 68 * @var string 69 */ 70 var $_htmlbody; 71 /** 72 * contains the mime encoded text 73 * @var string 74 */ 75 var $_mime; 76 /** 77 * contains the multipart content 78 * @var string 79 */ 80 var $_multipart; 81 /** 82 * list of the attached images 83 * @var array 84 */ 85 var $_html_images = array(); 86 /** 87 * list of the attachements 88 * @var array 89 */ 90 var $_parts = array(); 91 /** 92 * Build parameters 93 * @var array 94 */ 95 var $_build_params = array(); 96 /** 97 * Headers for the mail 98 * @var array 99 */ 100 var $_headers = array(); 101 /** 102 * End Of Line sequence (for serialize) 103 * @var string 104 */ 105 var $_eol; 106 107 108 /** 109 * Constructor function 110 * 111 * @access public 112 */ 113 function Mail_mime($crlf = "\r\n") 114 { 115 $this->_setEOL($crlf); 116 $this->_build_params = array( 117 'text_encoding' => '7bit', 118 'html_encoding' => 'quoted-printable', 119 '7bit_wrap' => 998, 120 'html_charset' => 'ISO-8859-1', 121 'text_charset' => 'ISO-8859-1', 122 'head_charset' => 'ISO-8859-1' 123 ); 124 } 125 126 /** 127 * Wakeup (unserialize) - re-sets EOL constant 128 * 129 * @access private 130 */ 131 function __wakeup() 132 { 133 $this->_setEOL($this->_eol); 134 } 135 136 /** 137 * Accessor function to set the body text. Body text is used if 138 * it's not an html mail being sent or else is used to fill the 139 * text/plain part that emails clients who don't support 140 * html should show. 141 * 142 * @param string $data Either a string or 143 * the file name with the contents 144 * @param bool $isfile If true the first param should be treated 145 * as a file name, else as a string (default) 146 * @param bool $append If true the text or file is appended to 147 * the existing body, else the old body is 148 * overwritten 149 * @return mixed true on success or PEAR_Error object 150 * @access public 151 */ 152 function setTXTBody($data, $isfile = false, $append = false) 153 { 154 if (!$isfile) { 155 if (!$append) { 156 $this->_txtbody = $data; 157 } else { 158 $this->_txtbody .= $data; 159 } 160 } else { 161 $cont = $this->_file2str($data); 162 if (PEAR::isError($cont)) { 163 return $cont; 164 } 165 if (!$append) { 166 $this->_txtbody = $cont; 167 } else { 168 $this->_txtbody .= $cont; 169 } 170 } 171 return true; 172 } 173 174 /** 175 * Adds a html part to the mail 176 * 177 * @param string $data Either a string or the file name with the 178 * contents 179 * @param bool $isfile If true the first param should be treated 180 * as a file name, else as a string (default) 181 * @return mixed true on success or PEAR_Error object 182 * @access public 183 */ 184 function setHTMLBody($data, $isfile = false) 185 { 186 if (!$isfile) { 187 $this->_htmlbody = $data; 188 } else { 189 $cont = $this->_file2str($data); 190 if (PEAR::isError($cont)) { 191 return $cont; 192 } 193 $this->_htmlbody = $cont; 194 } 195 196 return true; 197 } 198 199 /** 200 * Adds an image to the list of embedded images. 201 * 202 * @param string $file The image file name OR image data itself 203 * @param string $c_type The content type 204 * @param string $name The filename of the image. 205 * Only use if $file is the image data 206 * @param bool $isfilename Whether $file is a filename or not 207 * Defaults to true 208 * @return mixed true on success or PEAR_Error object 209 * @access public 210 */ 211 function addHTMLImage($file, $c_type='application/octet-stream', 212 $name = '', $isfilename = true) 213 { 214 $filedata = ($isfilename === true) ? $this->_file2str($file) 215 : $file; 216 if ($isfilename === true) { 217 $filename = ($name == '' ? basename($file) : basename($name)); 218 } else { 219 $filename = basename($name); 220 } 221 if (PEAR::isError($filedata)) { 222 return $filedata; 223 } 224 $this->_html_images[] = array( 225 'body' => $filedata, 226 'name' => $filename, 227 'c_type' => $c_type, 228 'cid' => md5(uniqid(time())) 229 ); 230 return true; 231 } 232 233 /** 234 * Adds a file to the list of attachments. 235 * 236 * @param string $file The file name of the file to attach 237 * OR the file data itself 238 * @param string $c_type The content type 239 * @param string $name The filename of the attachment 240 * Only use if $file is the file data 241 * @param bool $isFilename Whether $file is a filename or not 242 * Defaults to true 243 * @return mixed true on success or PEAR_Error object 244 * @access public 245 */ 246 function addAttachment($file, $c_type = 'application/octet-stream', 247 $name = '', $isfilename = true, 248 $encoding = 'base64') 249 { 250 $filedata = ($isfilename === true) ? $this->_file2str($file) 251 : $file; 252 if ($isfilename === true) { 253 // Force the name the user supplied, otherwise use $file 254 $filename = (!empty($name)) ? $name : $file; 255 } else { 256 $filename = $name; 257 } 258 if (empty($filename)) { 259 return PEAR::raiseError( 260 'The supplied filename for the attachment can\'t be empty' 261 ); 262 } 263 $filename = basename($filename); 264 if (PEAR::isError($filedata)) { 265 return $filedata; 266 } 267 268 $this->_parts[] = array( 269 'body' => $filedata, 270 'name' => $filename, 271 'c_type' => $c_type, 272 'encoding' => $encoding 273 ); 274 return true; 275 } 276 277 /** 278 * Get the contents of the given file name as string 279 * 280 * @param string $file_name path of file to process 281 * @return string contents of $file_name 282 * @access private 283 */ 284 function &_file2str($file_name) 285 { 286 if (!is_readable($file_name)) { 287 return PEAR::raiseError('File is not readable ' . $file_name); 288 } 289 if (!$fd = fopen($file_name, 'rb')) { 290 return PEAR::raiseError('Could not open ' . $file_name); 291 } 292 $filesize = filesize($file_name); 293 if ($filesize == 0){ 294 $cont = ""; 295 }else{ 296 $cont = fread($fd, $filesize); 297 } 298 fclose($fd); 299 return $cont; 300 } 301 302 /** 303 * Adds a text subpart to the mimePart object and 304 * returns it during the build process. 305 * 306 * @param mixed The object to add the part to, or 307 * null if a new object is to be created. 308 * @param string The text to add. 309 * @return object The text mimePart object 310 * @access private 311 */ 312 function &_addTextPart(&$obj, $text) 313 { 314 $params['content_type'] = 'text/plain'; 315 $params['encoding'] = $this->_build_params['text_encoding']; 316 $params['charset'] = $this->_build_params['text_charset']; 317 if (is_object($obj)) { 318 return $obj->addSubpart($text, $params); 319 } else { 320 return new Mail_mimePart($text, $params); 321 } 322 } 323 324 /** 325 * Adds a html subpart to the mimePart object and 326 * returns it during the build process. 327 * 328 * @param mixed The object to add the part to, or 329 * null if a new object is to be created. 330 * @return object The html mimePart object 331 * @access private 332 */ 333 function &_addHtmlPart(&$obj) 334 { 335 $params['content_type'] = 'text/html'; 336 $params['encoding'] = $this->_build_params['html_encoding']; 337 $params['charset'] = $this->_build_params['html_charset']; 338 if (is_object($obj)) { 339 return $obj->addSubpart($this->_htmlbody, $params); 340 } else { 341 return new Mail_mimePart($this->_htmlbody, $params); 342 } 343 } 344 345 /** 346 * Creates a new mimePart object, using multipart/mixed as 347 * the initial content-type and returns it during the 348 * build process. 349 * 350 * @return object The multipart/mixed mimePart object 351 * @access private 352 */ 353 function &_addMixedPart() 354 { 355 $params['content_type'] = 'multipart/mixed'; 356 return new Mail_mimePart('', $params); 357 } 358 359 /** 360 * Adds a multipart/alternative part to a mimePart 361 * object (or creates one), and returns it during 362 * the build process. 363 * 364 * @param mixed The object to add the part to, or 365 * null if a new object is to be created. 366 * @return object The multipart/mixed mimePart object 367 * @access private 368 */ 369 function &_addAlternativePart(&$obj) 370 { 371 $params['content_type'] = 'multipart/alternative'; 372 if (is_object($obj)) { 373 return $obj->addSubpart('', $params); 374 } else { 375 return new Mail_mimePart('', $params); 376 } 377 } 378 379 /** 380 * Adds a multipart/related part to a mimePart 381 * object (or creates one), and returns it during 382 * the build process. 383 * 384 * @param mixed The object to add the part to, or 385 * null if a new object is to be created 386 * @return object The multipart/mixed mimePart object 387 * @access private 388 */ 389 function &_addRelatedPart(&$obj) 390 { 391 $params['content_type'] = 'multipart/related'; 392 if (is_object($obj)) { 393 return $obj->addSubpart('', $params); 394 } else { 395 return new Mail_mimePart('', $params); 396 } 397 } 398 399 /** 400 * Adds an html image subpart to a mimePart object 401 * and returns it during the build process. 402 * 403 * @param object The mimePart to add the image to 404 * @param array The image information 405 * @return object The image mimePart object 406 * @access private 407 */ 408 function &_addHtmlImagePart(&$obj, $value) 409 { 410 $params['content_type'] = $value['c_type']; 411 $params['encoding'] = 'base64'; 412 $params['disposition'] = 'inline'; 413 $params['dfilename'] = $value['name']; 414 $params['cid'] = $value['cid']; 415 $obj->addSubpart($value['body'], $params); 416 } 417 418 /** 419 * Adds an attachment subpart to a mimePart object 420 * and returns it during the build process. 421 * 422 * @param object The mimePart to add the image to 423 * @param array The attachment information 424 * @return object The image mimePart object 425 * @access private 426 */ 427 function &_addAttachmentPart(&$obj, $value) 428 { 429 $params['content_type'] = $value['c_type']; 430 $params['encoding'] = $value['encoding']; 431 $params['disposition'] = 'attachment'; 432 $params['dfilename'] = $value['name']; 433 $obj->addSubpart($value['body'], $params); 434 } 435 436 /** 437 * Builds the multipart message from the list ($this->_parts) and 438 * returns the mime content. 439 * 440 * @param array Build parameters that change the way the email 441 * is built. Should be associative. Can contain: 442 * text_encoding - What encoding to use for plain text 443 * Default is 7bit 444 * html_encoding - What encoding to use for html 445 * Default is quoted-printable 446 * 7bit_wrap - Number of characters before text is 447 * wrapped in 7bit encoding 448 * Default is 998 449 * html_charset - The character set to use for html. 450 * Default is iso-8859-1 451 * text_charset - The character set to use for text. 452 * Default is iso-8859-1 453 * head_charset - The character set to use for headers. 454 * Default is iso-8859-1 455 * @return string The mime content 456 * @access public 457 */ 458 function &get($build_params = null) 459 { 460 if (isset($build_params)) { 461 while (list($key, $value) = each($build_params)) { 462 $this->_build_params[$key] = $value; 463 } 464 } 465 466 if (!empty($this->_html_images) AND isset($this->_htmlbody)) { 467 foreach ($this->_html_images as $value) { 468 $regex = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' . preg_quote($value['name'], '#') . 469 '\3#'; 470 $rep = '\1\2=\3cid:' . $value['cid'] .'\3'; 471 $this->_htmlbody = preg_replace($regex, $rep, 472 $this->_htmlbody 473 ); 474 } 475 } 476 477 $null = null; 478 $attachments = !empty($this->_parts) ? true : false; 479 $html_images = !empty($this->_html_images) ? true : false; 480 $html = !empty($this->_htmlbody) ? true : false; 481 $text = (!$html AND !empty($this->_txtbody)) ? true : false; 482 483 switch (true) { 484 case $text AND !$attachments: 485 $message =& $this->_addTextPart($null, $this->_txtbody); 486 break; 487 488 case !$text AND !$html AND $attachments: 489 $message =& $this->_addMixedPart(); 490 for ($i = 0; $i < count($this->_parts); $i++) { 491 $this->_addAttachmentPart($message, $this->_parts[$i]); 492 } 493 break; 494 495 case $text AND $attachments: 496 $message =& $this->_addMixedPart(); 497 $this->_addTextPart($message, $this->_txtbody); 498 for ($i = 0; $i < count($this->_parts); $i++) { 499 $this->_addAttachmentPart($message, $this->_parts[$i]); 500 } 501 break; 502 503 case $html AND !$attachments AND !$html_images: 504 if (isset($this->_txtbody)) { 505 $message =& $this->_addAlternativePart($null); 506 $this->_addTextPart($message, $this->_txtbody); 507 $this->_addHtmlPart($message); 508 } else { 509 $message =& $this->_addHtmlPart($null); 510 } 511 break; 512 513 case $html AND !$attachments AND $html_images: 514 if (isset($this->_txtbody)) { 515 $message =& $this->_addAlternativePart($null); 516 $this->_addTextPart($message, $this->_txtbody); 517 $related =& $this->_addRelatedPart($message); 518 } else { 519 $message =& $this->_addRelatedPart($null); 520 $related =& $message; 521 } 522 $this->_addHtmlPart($related); 523 for ($i = 0; $i < count($this->_html_images); $i++) { 524 $this->_addHtmlImagePart($related, $this->_html_images[$i]); 525 } 526 break; 527 528 case $html AND $attachments AND !$html_images: 529 $message =& $this->_addMixedPart(); 530 if (isset($this->_txtbody)) { 531 $alt =& $this->_addAlternativePart($message); 532 $this->_addTextPart($alt, $this->_txtbody); 533 $this->_addHtmlPart($alt); 534 } else { 535 $this->_addHtmlPart($message); 536 } 537 for ($i = 0; $i < count($this->_parts); $i++) { 538 $this->_addAttachmentPart($message, $this->_parts[$i]); 539 } 540 break; 541 542 case $html AND $attachments AND $html_images: 543 $message =& $this->_addMixedPart(); 544 if (isset($this->_txtbody)) { 545 $alt =& $this->_addAlternativePart($message); 546 $this->_addTextPart($alt, $this->_txtbody); 547 $rel =& $this->_addRelatedPart($alt); 548 } else { 549 $rel =& $this->_addRelatedPart($message); 550 } 551 $this->_addHtmlPart($rel); 552 for ($i = 0; $i < count($this->_html_images); $i++) { 553 $this->_addHtmlImagePart($rel, $this->_html_images[$i]); 554 } 555 for ($i = 0; $i < count($this->_parts); $i++) { 556 $this->_addAttachmentPart($message, $this->_parts[$i]); 557 } 558 break; 559 560 } 561 562 if (isset($message)) { 563 $output = $message->encode(); 564 $this->_headers = array_merge($this->_headers, 565 $output['headers']); 566 return $output['body']; 567 568 } else { 569 return false; 570 } 571 } 572 573 /** 574 * Returns an array with the headers needed to prepend to the email 575 * (MIME-Version and Content-Type). Format of argument is: 576 * $array['header-name'] = 'header-value'; 577 * 578 * @param array $xtra_headers Assoc array with any extra headers. 579 * Optional. 580 * @return array Assoc array with the mime headers 581 * @access public 582 */ 583 function &headers($xtra_headers = null) 584 { 585 // Content-Type header should already be present, 586 // So just add mime version header 587 $headers['MIME-Version'] = '1.0'; 588 if (isset($xtra_headers)) { 589 $headers = array_merge($headers, $xtra_headers); 590 } 591 $this->_headers = array_merge($headers, $this->_headers); 592 593 return $this->_encodeHeaders($this->_headers); 594 } 595 596 /** 597 * Get the text version of the headers 598 * (usefull if you want to use the PHP mail() function) 599 * 600 * @param array $xtra_headers Assoc array with any extra headers. 601 * Optional. 602 * @return string Plain text headers 603 * @access public 604 */ 605 function txtHeaders($xtra_headers = null) 606 { 607 $headers = $this->headers($xtra_headers); 608 $ret = ''; 609 foreach ($headers as $key => $val) { 610 $ret .= "$key: $val" . MAIL_MIME_CRLF; 611 } 612 return $ret; 613 } 614 615 /** 616 * Sets the Subject header 617 * 618 * @param string $subject String to set the subject to 619 * access public 620 */ 621 function setSubject($subject) 622 { 623 $this->_headers['Subject'] = $subject; 624 } 625 626 /** 627 * Set an email to the From (the sender) header 628 * 629 * @param string $email The email direction to add 630 * @access public 631 */ 632 function setFrom($email) 633 { 634 $this->_headers['From'] = $email; 635 } 636 637 /** 638 * Add an email to the Cc (carbon copy) header 639 * (multiple calls to this method are allowed) 640 * 641 * @param string $email The email direction to add 642 * @access public 643 */ 644 function addCc($email) 645 { 646 if (isset($this->_headers['Cc'])) { 647 $this->_headers['Cc'] .= ", $email"; 648 } else { 649 $this->_headers['Cc'] = $email; 650 } 651 } 652 653 /** 654 * Add an email to the Bcc (blank carbon copy) header 655 * (multiple calls to this method are allowed) 656 * 657 * @param string $email The email direction to add 658 * @access public 659 */ 660 function addBcc($email) 661 { 662 if (isset($this->_headers['Bcc'])) { 663 $this->_headers['Bcc'] .= ", $email"; 664 } else { 665 $this->_headers['Bcc'] = $email; 666 } 667 } 668 669 /** 670 * Encodes a header as per RFC2047 671 * 672 * @param string $input The header data to encode 673 * @return string Encoded data 674 * @access private 675 */ 676 function _encodeHeaders($input) 677 { 678 foreach ($input as $hdr_name => $hdr_value) { 679 preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $hdr_value, $matches); 680 foreach ($matches[1] as $value) { 681 $replacement = preg_replace('/([\x80-\xFF])/e', 682 '"=" . 683 strtoupper(dechex(ord("\1")))', 684 $value); 685 $hdr_value = str_replace($value, '=?' . 686 $this->_build_params['head_charset'] . 687 '?Q?' . $replacement . '?=', 688 $hdr_value); 689 } 690 $input[$hdr_name] = $hdr_value; 691 } 692 693 return $input; 694 } 695 696 /** 697 * Set the object's end-of-line and define the constant if applicable 698 * 699 * @param string $eol End Of Line sequence 700 * @access private 701 */ 702 function _setEOL($eol) 703 { 704 $this->_eol = $eol; 705 if (!defined('MAIL_MIME_CRLF')) { 706 define('MAIL_MIME_CRLF', $this->_eol, true); 707 } 708 } 709 710 711 712 } // End of class 713 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 14:40:03 2007 | par Balluche grâce à PHPXref 0.7 |