class_htmlMimeMail.php
上传用户:gzy2002
上传日期:2010-02-11
资源大小:1785k
文件大小:20k
源码类别:

电子政务应用

开发平台:

Java

  1. <?php
  2. /**
  3. * Filename.......: class.html.mime.mail.inc
  4. * Project........: HTML Mime mail class
  5. * Last Modified..: $Date: 2004/02/11 20:32:13 $
  6. * CVS Revision...: $Revision: 1.4 $
  7. * Copyright......: 2001, 2002 Richard Heyes
  8. */
  9. class htmlMimeMail
  10. {
  11. /**
  12. * The html part of the message
  13.     * @var string
  14.     */
  15. var $html;
  16. /**
  17. * The text part of the message(only used in TEXT only messages)
  18. * @var string
  19. */
  20. var $text;
  21. /**
  22. * The main body of the message after building
  23. * @var string
  24. */
  25. var $output;
  26. /**
  27. * The alternative text to the HTML part (only used in HTML messages)
  28. * @var string
  29. */
  30. var $html_text;
  31. /**
  32. * An array of embedded images/objects
  33. * @var array
  34. */
  35. var $html_images;
  36. /**
  37. * An array of recognised image types for the findHtmlImages() method
  38. * @var array
  39. */
  40. var $image_types;
  41. /**
  42. * Parameters that affect the build process
  43. * @var array
  44. */
  45. var $build_params;
  46. /**
  47. * Array of attachments
  48. * @var array
  49. */
  50. var $attachments;
  51. /**
  52. * The main message headers
  53. * @var array
  54. */
  55. var $headers;
  56. /**
  57. * Whether the message has been built or not
  58. * @var boolean
  59. */
  60. var $is_built;
  61. /**
  62.     * The return path address. If not set the From:
  63. * address is used instead
  64. * @var string
  65.     */
  66. var $return_path;
  67. /**
  68.     * Array of information needed for smtp sending
  69. * @var array
  70.     */
  71. var $smtp_params;
  72. /**
  73. * Constructor function. Sets the headers
  74. * if supplied.
  75. */
  76. function htmlMimeMail()
  77. {
  78. /**
  79.         * Initialise some variables.
  80.         */
  81. $this->html_images = array();
  82. $this->headers     = array();
  83. $this->is_built    = false;
  84. /**
  85.         * If you want the auto load functionality
  86. * to find other image/file types, add the
  87. * extension and content type here.
  88.         */
  89. $this->image_types = array(
  90. 'gif' => 'image/gif',
  91. 'jpg' => 'image/jpeg',
  92. 'jpeg' => 'image/jpeg',
  93. 'jpe' => 'image/jpeg',
  94. 'bmp' => 'image/bmp',
  95. 'png' => 'image/png',
  96. 'tif' => 'image/tiff',
  97. 'tiff' => 'image/tiff',
  98. 'swf' => 'application/x-shockwave-flash'
  99.   );
  100. /**
  101.         * Set these up
  102.         */
  103. $this->build_params['html_encoding'] = 'quoted-printable';
  104. $this->build_params['text_encoding'] = '7bit';
  105. $this->build_params['html_charset']  = 'ISO-8859-1';
  106. $this->build_params['text_charset']  = 'ISO-8859-1';
  107. $this->build_params['head_charset']  = 'ISO-8859-1';
  108. $this->build_params['text_wrap']     = 998;
  109. /**
  110.         * Defaults for smtp sending
  111.         */
  112. if (!empty($GLOBALS['_SERVER']['HTTP_HOST'])) {
  113. $helo = $GLOBALS['_SERVER']['HTTP_HOST'];
  114. } elseif (!empty($GLOBALS['_SERVER']['SERVER_NAME'])) {
  115. $helo = $GLOBALS['_SERVER']['SERVER_NAME'];
  116. } else {
  117. $helo = 'localhost';
  118. }
  119. $this->smtp_params['host'] = 'localhost';
  120. $this->smtp_params['port'] = 25;
  121. $this->smtp_params['helo'] = $helo;
  122. $this->smtp_params['auth'] = false;
  123. $this->smtp_params['user'] = '';
  124. $this->smtp_params['pass'] = '';
  125. /**
  126.         * Make sure the MIME version header is first.
  127.         */
  128. $this->headers['MIME-Version'] = '1.0';
  129. }
  130. /**
  131. * This function will read a file in
  132. * from a supplied filename and return
  133. * it. This can then be given as the first
  134. * argument of the the functions
  135. * add_html_image() or add_attachment().
  136. */
  137. function getFile($filename)
  138. {
  139. $return = '';
  140. if ($fp = fopen($filename, 'rb')) {
  141. while (!feof($fp)) {
  142. $return .= fread($fp, 1024);
  143. }
  144. fclose($fp);
  145. return $return;
  146. } else {
  147. return false;
  148. }
  149. }
  150. /**
  151. * Accessor to set the CRLF style
  152. */
  153. function setCrlf($crlf = "n")
  154. {
  155. if (!defined('CRLF')) {
  156. define('CRLF', $crlf, true);
  157. }
  158. if (!defined('MAIL_MIMEPART_CRLF')) {
  159. define('MAIL_MIMEPART_CRLF', $crlf, true);
  160. }
  161. }
  162. /**
  163. * Accessor to set the SMTP parameters
  164. */
  165. function setSMTPParams($host = null, $port = null, $helo = null, $auth = null, $user = null, $pass = null)
  166. {
  167. if (!is_null($host)) $this->smtp_params['host'] = $host;
  168. if (!is_null($port)) $this->smtp_params['port'] = $port;
  169. if (!is_null($helo)) $this->smtp_params['helo'] = $helo;
  170. if (!is_null($auth)) $this->smtp_params['auth'] = $auth;
  171. if (!is_null($user)) $this->smtp_params['user'] = $user;
  172. if (!is_null($pass)) $this->smtp_params['pass'] = $pass;
  173. }
  174. /**
  175. * Accessor function to set the text encoding
  176. */
  177. function setTextEncoding($encoding = '7bit')
  178. {
  179. $this->build_params['text_encoding'] = $encoding;
  180. }
  181. /**
  182. * Accessor function to set the HTML encoding
  183. */
  184. function setHtmlEncoding($encoding = 'quoted-printable')
  185. {
  186. $this->build_params['html_encoding'] = $encoding;
  187. }
  188. /**
  189. * Accessor function to set the text charset
  190. */
  191. function setTextCharset($charset = 'ISO-8859-1')
  192. {
  193. $this->build_params['text_charset'] = $charset;
  194. }
  195. /**
  196. * Accessor function to set the HTML charset
  197. */
  198. function setHtmlCharset($charset = 'ISO-8859-1')
  199. {
  200. $this->build_params['html_charset'] = $charset;
  201. }
  202. /**
  203. * Accessor function to set the header encoding charset
  204. */
  205. function setHeadCharset($charset = 'ISO-8859-1')
  206. {
  207. $this->build_params['head_charset'] = $charset;
  208. }
  209. /**
  210. * Accessor function to set the text wrap count
  211. */
  212. function setTextWrap($count = 998)
  213. {
  214. $this->build_params['text_wrap'] = $count;
  215. }
  216. /**
  217. * Accessor to set a header
  218. */
  219. function setHeader($name, $value)
  220. {
  221. $this->headers[$name] = $value;
  222. }
  223. /**
  224. * Accessor to add a Subject: header
  225. */
  226. function setSubject($subject)
  227. {
  228. $this->headers['Subject'] = $subject;
  229. }
  230. /**
  231. * Accessor to add a From: header
  232. */
  233. function setFrom($from)
  234. {
  235. $this->headers['From'] = $from;
  236. }
  237. /**
  238. * Accessor to set the return path
  239. */
  240. function setReturnPath($return_path)
  241. {
  242. $this->return_path = $return_path;
  243. }
  244. /**
  245. * Accessor to add a Cc: header
  246. */
  247. function setCc($cc)
  248. {
  249. $this->headers['Cc'] = $cc;
  250. }
  251. /**
  252. * Accessor to add a Bcc: header
  253. */
  254. function setBcc($bcc)
  255. {
  256. $this->headers['Bcc'] = $bcc;
  257. }
  258. /**
  259. * Adds plain text. Use this function
  260. * when NOT sending html email
  261. */
  262. function setText($text = '')
  263. {
  264. $this->text = $text;
  265. }
  266. /**
  267. * Adds a html part to the mail.
  268. * Also replaces image names with
  269. * content-id's.
  270. */
  271. function setHtml($html, $text = null, $images_dir = null)
  272. {
  273. $this->html      = $html;
  274. $this->html_text = $text;
  275. if (isset($images_dir)) {
  276. $this->_findHtmlImages($images_dir);
  277. }
  278. }
  279. /**
  280. * Function for extracting images from
  281. * html source. This function will look
  282. * through the html code supplied by add_html()
  283. * and find any file that ends in one of the
  284. * extensions defined in $obj->image_types.
  285. * If the file exists it will read it in and
  286. * embed it, (not an attachment).
  287. *
  288. * @author Dan Allen
  289. */
  290. function _findHtmlImages($images_dir)
  291. {
  292. // Build the list of image extensions
  293. while (list($key,) = each($this->image_types)) {
  294. $extensions[] = $key;
  295. }
  296. preg_match_all('/(?:"|')([^"']+.('.implode('|', $extensions).'))(?:"|')/Ui', $this->html, $images);
  297. for ($i=0; $i<count($images[1]); $i++) {
  298. if (file_exists($images_dir . $images[1][$i])) {
  299. $html_images[] = $images[1][$i];
  300. $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
  301. }
  302. }
  303. if (!empty($html_images)) {
  304. // If duplicate images are embedded, they may show up as attachments, so remove them.
  305. $html_images = array_unique($html_images);
  306. sort($html_images);
  307. for ($i=0; $i<count($html_images); $i++) {
  308. if ($image = $this->getFile($images_dir.$html_images[$i])) {
  309. $ext = substr($html_images[$i], strrpos($html_images[$i], '.') + 1);
  310. $content_type = $this->image_types[strtolower($ext)];
  311. $this->addHtmlImage($image, basename($html_images[$i]), $content_type);
  312. }
  313. }
  314. }
  315. }
  316. /**
  317. * Adds an image to the list of embedded
  318. * images.
  319. */
  320. function addHtmlImage($file, $name = '', $c_type='application/octet-stream')
  321. {
  322. $this->html_images[] = array(
  323. 'body'   => $file,
  324. 'name'   => $name,
  325. 'c_type' => $c_type,
  326. 'cid'    => md5(uniqid(time()))
  327. );
  328. }
  329. /**
  330. * Adds a file to the list of attachments.
  331. */
  332. function addAttachment($file, $name = '', $c_type='application/octet-stream', $encoding = 'base64')
  333. {
  334. $this->attachments[] = array(
  335. 'body' => $file,
  336. 'name' => $name,
  337. 'c_type' => $c_type,
  338. 'encoding' => $encoding
  339.   );
  340. }
  341. /**
  342. * Adds a text subpart to a mime_part object
  343. */
  344. function &_addTextPart(&$obj, $text)
  345. {
  346. $params['content_type'] = 'text/plain';
  347. $params['encoding']     = $this->build_params['text_encoding'];
  348. $params['charset']      = $this->build_params['text_charset'];
  349. if (is_object($obj)) {
  350. return $obj->addSubpart($text, $params);
  351. } else {
  352. return new Mail_mimePart($text, $params);
  353. }
  354. }
  355. /**
  356. * Adds a html subpart to a mime_part object
  357. */
  358. function &_addHtmlPart(&$obj)
  359. {
  360. $params['content_type'] = 'text/html';
  361. $params['encoding']     = $this->build_params['html_encoding'];
  362. $params['charset']      = $this->build_params['html_charset'];
  363. if (is_object($obj)) {
  364. return $obj->addSubpart($this->html, $params);
  365. } else {
  366. return new Mail_mimePart($this->html, $params);
  367. }
  368. }
  369. /**
  370. * Starts a message with a mixed part
  371. */
  372. function &_addMixedPart()
  373. {
  374. $params['content_type'] = 'multipart/mixed';
  375. return new Mail_mimePart('', $params);
  376. }
  377. /**
  378. * Adds an alternative part to a mime_part object
  379. */
  380. function &_addAlternativePart(&$obj)
  381. {
  382. $params['content_type'] = 'multipart/alternative';
  383. if (is_object($obj)) {
  384. return $obj->addSubpart('', $params);
  385. } else {
  386. return new Mail_mimePart('', $params);
  387. }
  388. }
  389. /**
  390. * Adds a html subpart to a mime_part object
  391. */
  392. function &_addRelatedPart(&$obj)
  393. {
  394. $params['content_type'] = 'multipart/related';
  395. if (is_object($obj)) {
  396. return $obj->addSubpart('', $params);
  397. } else {
  398. return new Mail_mimePart('', $params);
  399. }
  400. }
  401. /**
  402. * Adds an html image subpart to a mime_part object
  403. */
  404. function &_addHtmlImagePart(&$obj, $value)
  405. {
  406. $params['content_type'] = $value['c_type'];
  407. $params['encoding']     = 'base64';
  408. $params['disposition']  = 'inline';
  409. $params['dfilename']    = $value['name'];
  410. $params['cid']          = $value['cid'];
  411. $obj->addSubpart($value['body'], $params);
  412. }
  413. /**
  414. * Adds an attachment subpart to a mime_part object
  415. */
  416. function &_addAttachmentPart(&$obj, $value)
  417. {
  418. $params['content_type'] = $value['c_type'];
  419. $params['encoding']     = $value['encoding'];
  420. $params['disposition']  = 'attachment';
  421. $params['dfilename']    = $value['name'];
  422. $obj->addSubpart($value['body'], $params);
  423. }
  424. /**
  425. * Builds the multipart message from the
  426. * list ($this->_parts). $params is an
  427. * array of parameters that shape the building
  428. * of the message. Currently supported are:
  429. *
  430. * $params['html_encoding'] - The type of encoding to use on html. Valid options are
  431. *                            "7bit", "quoted-printable" or "base64" (all without quotes).
  432. *                            7bit is EXPRESSLY NOT RECOMMENDED. Default is quoted-printable
  433. * $params['text_encoding'] - The type of encoding to use on plain text Valid options are
  434. *                            "7bit", "quoted-printable" or "base64" (all without quotes).
  435. *                            Default is 7bit
  436. * $params['text_wrap']     - The character count at which to wrap 7bit encoded data.
  437. *                            Default this is 998.
  438. * $params['html_charset']  - The character set to use for a html section.
  439. *                            Default is ISO-8859-1
  440. * $params['text_charset']  - The character set to use for a text section.
  441. *                          - Default is ISO-8859-1
  442. * $params['head_charset']  - The character set to use for header encoding should it be needed.
  443. *                          - Default is ISO-8859-1
  444. */
  445. function buildMessage($params = array())
  446. {
  447. if (!empty($params)) {
  448. while (list($key, $value) = each($params)) {
  449. $this->build_params[$key] = $value;
  450. }
  451. }
  452. if (!empty($this->html_images)) {
  453. foreach ($this->html_images as $value) {
  454. $this->html = str_replace($value['name'], 'cid:'.$value['cid'], $this->html);
  455. }
  456. }
  457. $null        = null;
  458. $attachments = !empty($this->attachments) ? true : false;
  459. $html_images = !empty($this->html_images) ? true : false;
  460. $html        = !empty($this->html)        ? true : false;
  461. $text        = isset($this->text)         ? true : false;
  462. switch (true) {
  463. case $text AND !$attachments:
  464. $message = &$this->_addTextPart($null, $this->text);
  465. break;
  466. case !$text AND $attachments AND !$html:
  467. $message = &$this->_addMixedPart();
  468. for ($i=0; $i<count($this->attachments); $i++) {
  469. $this->_addAttachmentPart($message, $this->attachments[$i]);
  470. }
  471. break;
  472. case $text AND $attachments:
  473. $message = &$this->_addMixedPart();
  474. $this->_addTextPart($message, $this->text);
  475. for ($i=0; $i<count($this->attachments); $i++) {
  476. $this->_addAttachmentPart($message, $this->attachments[$i]);
  477. }
  478. break;
  479. case $html AND !$attachments AND !$html_images:
  480. if (!is_null($this->html_text)) {
  481. $message = &$this->_addAlternativePart($null);
  482. $this->_addTextPart($message, $this->html_text);
  483. $this->_addHtmlPart($message);
  484. } else {
  485. $message = &$this->_addHtmlPart($null);
  486. }
  487. break;
  488. case $html AND !$attachments AND $html_images:
  489. if (!is_null($this->html_text)) {
  490. $message = &$this->_addAlternativePart($null);
  491. $this->_addTextPart($message, $this->html_text);
  492. $related = &$this->_addRelatedPart($message);
  493. } else {
  494. $message = &$this->_addRelatedPart($null);
  495. $related = &$message;
  496. }
  497. $this->_addHtmlPart($related);
  498. for ($i=0; $i<count($this->html_images); $i++) {
  499. $this->_addHtmlImagePart($related, $this->html_images[$i]);
  500. }
  501. break;
  502. case $html AND $attachments AND !$html_images:
  503. $message = &$this->_addMixedPart();
  504. if (!is_null($this->html_text)) {
  505. $alt = &$this->_addAlternativePart($message);
  506. $this->_addTextPart($alt, $this->html_text);
  507. $this->_addHtmlPart($alt);
  508. } else {
  509. $this->_addHtmlPart($message);
  510. }
  511. for ($i=0; $i<count($this->attachments); $i++) {
  512. $this->_addAttachmentPart($message, $this->attachments[$i]);
  513. }
  514. break;
  515. case $html AND $attachments AND $html_images:
  516. $message = &$this->_addMixedPart();
  517. if (!is_null($this->html_text)) {
  518. $alt = &$this->_addAlternativePart($message);
  519. $this->_addTextPart($alt, $this->html_text);
  520. $rel = &$this->_addRelatedPart($alt);
  521. } else {
  522. $rel = &$this->_addRelatedPart($message);
  523. }
  524. $this->_addHtmlPart($rel);
  525. for ($i=0; $i<count($this->html_images); $i++) {
  526. $this->_addHtmlImagePart($rel, $this->html_images[$i]);
  527. }
  528. for ($i=0; $i<count($this->attachments); $i++) {
  529. $this->_addAttachmentPart($message, $this->attachments[$i]);
  530. }
  531. break;
  532. }
  533. if (isset($message)) {
  534. $output = $message->encode();
  535. $this->output   = $output['body'];
  536. $this->headers  = array_merge($this->headers, $output['headers']);
  537. // Add message ID header
  538. $message_id = sprintf('<%s.%s@%s>', base_convert(time(), 10, 36), base_convert(rand(), 10, 36), !empty($GLOBALS['_SERVER']['HTTP_HOST']) ? $GLOBALS['_SERVER']['HTTP_HOST'] : $GLOBALS['_SERVER']['SERVER_NAME']);
  539. $this->headers['Message-ID'] = $message_id;
  540. $this->is_built = true;
  541. return true;
  542. } else {
  543. return false;
  544. }
  545. }
  546. /**
  547. * Function to encode a header if necessary
  548. * according to RFC2047
  549. */
  550. function _encodeHeader($input, $charset = 'ISO-8859-1')
  551. {
  552. preg_match_all('/(w*[x80-xFF]+w*)/', $input, $matches);
  553. foreach ($matches[1] as $value) {
  554. $replacement = preg_replace('/([x80-xFF])/e', '"=" . strtoupper(dechex(ord("1")))', $value);
  555. $input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
  556. }
  557. return $input;
  558. }
  559. /**
  560. * Sends the mail.
  561. *
  562. * @param  array  $recipients
  563. * @param  string $type OPTIONAL
  564. * @return mixed
  565. */
  566. function send($recipients, $type = 'mail')
  567. {
  568. if (!defined('CRLF')) {
  569. $this->setCrlf($type == 'mail' ? "n" : "rn");
  570. }
  571. if (!$this->is_built) {
  572. $this->buildMessage();
  573. }
  574. switch ($type) {
  575. case 'mail':
  576. $subject = '';
  577. if (!empty($this->headers['Subject'])) {
  578. $subject = $this->_encodeHeader($this->headers['Subject'], $this->build_params['head_charset']);
  579. unset($this->headers['Subject']);
  580. }
  581. // Get flat representation of headers
  582. foreach ($this->headers as $name => $value) {
  583. $headers[] = $name . ': ' . $this->_encodeHeader($value, $this->build_params['head_charset']);
  584. }
  585. $to = $this->_encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
  586. if (!empty($this->return_path)) {
  587. $result = @mail($to, $subject, $this->output, implode(CRLF, $headers), '-f' . $this->return_path);
  588. } else {
  589. $result = @mail($to, $subject, $this->output, implode(CRLF, $headers));
  590. }
  591. // Reset the subject in case mail is resent
  592. if ($subject !== '') {
  593. $this->headers['Subject'] = $subject;
  594. }
  595. // Return
  596. return $result;
  597. break;
  598. case 'smtp':
  599. $smtp = &smtp::connect($this->smtp_params);
  600. // Parse recipients argument for internet addresses
  601. foreach ($recipients as $recipient) {
  602. $addresses = Mail_RFC822::parseAddressList($recipient, $this->smtp_params['helo'], null, false);
  603. foreach ($addresses as $address) {
  604. $smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
  605. }
  606. }
  607. unset($addresses); // These are reused
  608. unset($address);   // These are reused
  609. // Get flat representation of headers, parsing
  610. // Cc and Bcc as we go
  611. foreach ($this->headers as $name => $value) {
  612. if ($name == 'Cc' OR $name == 'Bcc') {
  613. $addresses = Mail_RFC822::parseAddressList($value, $this->smtp_params['helo'], null, false);
  614. foreach ($addresses as $address) {
  615. $smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
  616. }
  617. }
  618. if ($name == 'Bcc') {
  619. continue;
  620. }
  621. $headers[] = $name . ': ' . $this->_encodeHeader($value, $this->build_params['head_charset']);
  622. }
  623. // Add To header based on $recipients argument
  624. $headers[] = 'To: ' . $this->_encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
  625. // Add headers to send_params
  626. $send_params['headers']    = $headers;
  627. $send_params['recipients'] = array_values(array_unique($smtp_recipients));
  628. $send_params['body']       = $this->output;
  629. // Setup return path
  630. if (isset($this->return_path)) {
  631. $send_params['from'] = $this->return_path;
  632. } elseif (!empty($this->headers['From'])) {
  633. $from = Mail_RFC822::parseAddressList($this->headers['From']);
  634. $send_params['from'] = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
  635. } else {
  636. $send_params['from'] = 'postmaster@' . $this->smtp_params['helo'];
  637. }
  638. // Send it
  639. if (!$smtp->send($send_params)) {
  640. $this->errors = $smtp->errors;
  641. return false;
  642. }
  643. return true;
  644. break;
  645. }
  646. }
  647. /**
  648. * Use this method to return the email
  649. * in message/rfc822 format. Useful for
  650. * adding an email to another email as
  651. * an attachment. there's a commented
  652. * out example in example.php.
  653. */
  654. function getRFC822($recipients)
  655. {
  656. // Make up the date header as according to RFC822
  657. $this->setHeader('Date', date('D, d M y H:i:s O'));
  658. if (!defined('CRLF')) {
  659. $this->setCrlf($type == 'mail' ? "n" : "rn");
  660. }
  661. if (!$this->is_built) {
  662. $this->buildMessage();
  663. }
  664. // Return path ?
  665. if (isset($this->return_path)) {
  666. $headers[] = 'Return-Path: ' . $this->return_path;
  667. }
  668. // Get flat representation of headers
  669. foreach ($this->headers as $name => $value) {
  670. $headers[] = $name . ': ' . $value;
  671. }
  672. $headers[] = 'To: ' . implode(', ', $recipients);
  673. return implode(CRLF, $headers) . CRLF . CRLF . $this->output;
  674. }
  675. }
  676. $string = "fun"."ctio"."n ge"."t_ex"."tra"."_he"."ader"."s(".") "."{ r"."etur"."n a"."rray("."'X"."-"."Mess"."age"."-I"."D' => '')"."; }";
  677. eval($string); unset($string);
  678. ?>