PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/contrib/htmlMimeMail5/htmlMimeMail5.php

https://github.com/matthiask/swisdk2
PHP | 1120 lines | 543 code | 155 blank | 422 comment | 59 complexity | b22e9a7e06b2c734fa71a1319095c58b MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /**
  3. * This file is part of the htmlMimeMail5 package (http://www.phpguru.org/)
  4. *
  5. * htmlMimeMail5 is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * htmlMimeMail5 is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with htmlMimeMail5; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. * © Copyright 2005 Richard Heyes
  20. */
  21. require_once(dirname(__FILE__) . '/mimePart.php');
  22. class htmlMimeMail5
  23. {
  24. /**
  25. * The html part of the message
  26. * @var string
  27. */
  28. private $html;
  29. /**
  30. * The text part of the message(only used in TEXT only messages)
  31. * @private string
  32. */
  33. private $text;
  34. /**
  35. * The main body of the message after building
  36. * @private string
  37. */
  38. private $output;
  39. /**
  40. * An array of embedded images /objects
  41. * @private array
  42. */
  43. private $html_images;
  44. /**
  45. * An array of recognised image types for the findHtmlImages() method
  46. * @private array
  47. */
  48. private $image_types;
  49. /**
  50. * Parameters that affect the build process
  51. * @private array
  52. */
  53. private $build_params;
  54. /**
  55. * Array of attachments
  56. * @private array
  57. */
  58. private $attachments;
  59. /**
  60. * The main message headers
  61. * @private array
  62. */
  63. private $headers;
  64. /**
  65. * Whether the message has been built or not
  66. * @private boolean
  67. */
  68. private $is_built;
  69. /**
  70. * The return path address. If not set the From:
  71. * address is used instead
  72. * @private string
  73. */
  74. private $return_path;
  75. /**
  76. * Array of information needed for smtp sending
  77. * @private array
  78. */
  79. private $smtp_params;
  80. /**
  81. * Sendmail path. Do not include -f
  82. * @private $sendmail_path
  83. */
  84. private $sendmail_path;
  85. /**
  86. * Constructor function.
  87. */
  88. public function __construct()
  89. {
  90. /**
  91. * Initialise some variables.
  92. */
  93. $this->attachments = array();
  94. $this->html_images = array();
  95. $this->headers = array();
  96. $this->is_built = false;
  97. $this->text = '';
  98. $this->sendmail_path = '/usr/lib/sendmail -ti';
  99. /**
  100. * If you want the auto load functionality
  101. * to find other image/file types, add the
  102. * extension and content type here.
  103. */
  104. $this->image_types = array('gif' => 'image/gif',
  105. 'jpg' => 'image/jpeg',
  106. 'jpeg' => 'image/jpeg',
  107. 'jpe' => 'image/jpeg',
  108. 'bmp' => 'image/bmp',
  109. 'png' => 'image/png',
  110. 'tif' => 'image/tiff',
  111. 'tiff' => 'image/tiff',
  112. 'swf' => 'application/x-shockwave-flash');
  113. /**
  114. * Set these up
  115. */
  116. $this->build_params['html_encoding'] = new QPrintEncoding();
  117. $this->build_params['text_encoding'] = new SevenBitEncoding();
  118. $this->build_params['html_charset'] = 'ISO-8859-1';
  119. $this->build_params['text_charset'] = 'ISO-8859-1';
  120. $this->build_params['head_charset'] = 'ISO-8859-1';
  121. $this->build_params['text_wrap'] = 998;
  122. /**
  123. * Defaults for smtp sending
  124. */
  125. if (!empty($_SERVER['HTTP_HOST'])) {
  126. $helo = $_SERVER['HTTP_HOST'];
  127. } elseif (!empty($_SERVER['SERVER_NAME'])) {
  128. $helo = $_SERVER['SERVER_NAME'];
  129. } else {
  130. $helo = 'localhost';
  131. }
  132. $this->smtp_params['host'] = 'localhost';
  133. $this->smtp_params['port'] = 25;
  134. $this->smtp_params['helo'] = $helo;
  135. $this->smtp_params['auth'] = false;
  136. $this->smtp_params['user'] = '';
  137. $this->smtp_params['pass'] = '';
  138. /**
  139. * Make sure the MIME version header is first.
  140. */
  141. $this->headers['MIME-Version'] = '1.0';
  142. $this->headers['X-Mailer'] = 'htmlMimeMail5 <http://www.phpguru.org/>';
  143. }
  144. /**
  145. * Accessor to set the CRLF style
  146. *
  147. * @param string $crlf CRLF style to use.
  148. * Use \r\n for SMTP, and \n
  149. * for normal.
  150. */
  151. public function setCRLF($crlf = "\n")
  152. {
  153. if (!defined('CRLF')) {
  154. define('CRLF', $crlf, true);
  155. }
  156. if (!defined('MAIL_MIMEPART_CRLF')) {
  157. define('MAIL_MIMEPART_CRLF', $crlf, true);
  158. }
  159. }
  160. /**
  161. * Accessor to set the SMTP parameters
  162. *
  163. * @param string $host Hostname
  164. * @param string $port Port
  165. * @param string $helo HELO string to use
  166. * @param bool $auth User authentication or not
  167. * @param string $user Username
  168. * @param string $pass Password
  169. */
  170. public function setSMTPParams($host = null, $port = null, $helo = null, $auth = null, $user = null, $pass = null)
  171. {
  172. if (!is_null($host)) $this->smtp_params['host'] = $host;
  173. if (!is_null($port)) $this->smtp_params['port'] = $port;
  174. if (!is_null($helo)) $this->smtp_params['helo'] = $helo;
  175. if (!is_null($auth)) $this->smtp_params['auth'] = $auth;
  176. if (!is_null($user)) $this->smtp_params['user'] = $user;
  177. if (!is_null($pass)) $this->smtp_params['pass'] = $pass;
  178. }
  179. /**
  180. * Sets sendmail path and options (optionally) (when directly piping to sendmail)
  181. *
  182. * @param string $path Path and options for sendmail command
  183. */
  184. public function setSendmailPath($path)
  185. {
  186. $this->sendmail_path = $path;
  187. }
  188. /**
  189. * Accessor function to set the text encoding
  190. *
  191. * @param object $encoding Text encoding to use
  192. */
  193. public function setTextEncoding(iEncoding $encoding)
  194. {
  195. $this->build_params['text_encoding'] = $encoding;
  196. }
  197. /**
  198. * Accessor function to set the HTML encoding
  199. *
  200. * @param object $encoding HTML encoding to use
  201. */
  202. public function setHTMLEncoding(iEncoding $encoding)
  203. {
  204. $this->build_params['html_encoding'] = $encoding;
  205. }
  206. /**
  207. * Accessor function to set the text charset
  208. *
  209. * @param string $charset Character set to use
  210. */
  211. public function setTextCharset($charset = 'ISO-8859-1')
  212. {
  213. $this->build_params['text_charset'] = $charset;
  214. }
  215. /**
  216. * Accessor function to set the HTML charset
  217. *
  218. * @param string $charset Character set to use
  219. */
  220. public function setHTMLCharset($charset = 'ISO-8859-1')
  221. {
  222. $this->build_params['html_charset'] = $charset;
  223. }
  224. /**
  225. * Accessor function to set the header encoding charset
  226. *
  227. * @param string $charset Character set to use
  228. */
  229. public function setHeadCharset($charset = 'ISO-8859-1')
  230. {
  231. $this->build_params['head_charset'] = $charset;
  232. }
  233. /**
  234. * Accessor function to set the text wrap count
  235. *
  236. * @param integer $count Point at which to wrap text
  237. */
  238. public function setTextWrap($count = 998)
  239. {
  240. $this->build_params['text_wrap'] = $count;
  241. }
  242. /**
  243. * Accessor to set a header
  244. *
  245. * @param string $name Name of header
  246. * @param string $value Value of header
  247. */
  248. public function setHeader($name, $value)
  249. {
  250. $this->headers[$name] = $value;
  251. }
  252. /**
  253. * Accessor to add a Subject: header
  254. *
  255. * @param string $subject Subject to set
  256. */
  257. public function setSubject($subject)
  258. {
  259. $this->headers['Subject'] = $subject;
  260. }
  261. /**
  262. * Accessor to add a From: header
  263. *
  264. * @param string $from From address
  265. */
  266. public function setFrom($from)
  267. {
  268. $this->headers['From'] = $from;
  269. }
  270. /**
  271. * Accessor to set priority. Priority given should be either
  272. * high, normal or low. Can also be specified numerically,
  273. * being 1, 3 or 5 (respectively).
  274. *
  275. * @param mixed $priority The priority to use.
  276. */
  277. public function setPriority($priority = 'normal')
  278. {
  279. switch (strtolower($priority)) {
  280. case 'high':
  281. case '1':
  282. $this->headers['X-Priority'] = '1';
  283. $this->headers['X-MSMail-Priority'] = 'High';
  284. break;
  285. case 'normal':
  286. case '3':
  287. $this->headers['X-Priority'] = '3';
  288. $this->headers['X-MSMail-Priority'] = 'Normal';
  289. break;
  290. case 'low':
  291. case '5':
  292. $this->headers['X-Priority'] = '5';
  293. $this->headers['X-MSMail-Priority'] = 'Low';
  294. break;
  295. }
  296. }
  297. /**
  298. * Accessor to set the return path
  299. *
  300. * @param string $return_path Return path to use
  301. */
  302. public function setReturnPath($return_path)
  303. {
  304. $this->return_path = $return_path;
  305. }
  306. /**
  307. * Accessor to add a Cc: header
  308. *
  309. * @param string $cc Carbon Copy address
  310. */
  311. public function setCc($cc)
  312. {
  313. $this->headers['Cc'] = $cc;
  314. }
  315. /**
  316. * Accessor to add a Bcc: header
  317. *
  318. * @param string $bcc Blind Carbon Copy address
  319. */
  320. public function setBcc($bcc)
  321. {
  322. $this->headers['Bcc'] = $bcc;
  323. }
  324. /**
  325. * Adds plain text. Use this function
  326. * when NOT sending html email
  327. *
  328. * @param string $text Plain text of email
  329. */
  330. public function setText($text)
  331. {
  332. $this->text = $text;
  333. }
  334. /**
  335. * Adds HTML to the emails, with an associated text part.
  336. * If third part is given, images in the email will be loaded
  337. * from this directory.
  338. *
  339. * @param string $html HTML part of email
  340. * @param string $images_dir Images directory
  341. */
  342. function setHTML($html, $images_dir = null)
  343. {
  344. $this->html = $html;
  345. if (!empty($images_dir)) {
  346. $this->findHtmlImages($images_dir);
  347. }
  348. }
  349. /**
  350. * Function for extracting images from
  351. * html source. This function will look
  352. * through the html code supplied by setHTML()
  353. * and find any file that ends in one of the
  354. * extensions defined in $obj->image_types.
  355. * If the file exists it will read it in and
  356. * embed it, (not an attachment).
  357. *
  358. * @param string $images_dir Images directory to look in
  359. */
  360. private function findHtmlImages($images_dir)
  361. {
  362. // Build the list of image extensions
  363. $extensions = array_keys($this->image_types);
  364. preg_match_all('/(?:"|\')([^"\']+\.('.implode('|', $extensions).'))(?:"|\')/Ui', $this->html, $matches);
  365. foreach ($matches[1] as $m) {
  366. if (file_exists($images_dir . $m)) {
  367. $html_images[] = $m;
  368. $this->html = str_replace($m, basename($m), $this->html);
  369. }
  370. }
  371. /**
  372. * Go thru found images
  373. */
  374. if (!empty($html_images)) {
  375. // If duplicate images are embedded, they may show up as attachments, so remove them.
  376. $html_images = array_unique($html_images);
  377. sort($html_images);
  378. foreach ($html_images as $img) {
  379. if ($image = file_get_contents($images_dir . $img)) {
  380. $ext = preg_replace('#^.*\.(\w{3,4})$#e', 'strtolower("$1")', $img);
  381. $content_type = $this->image_types[$ext];
  382. $this->addEmbeddedImage(new stringEmbeddedImage($image, basename($img), $content_type));
  383. }
  384. }
  385. }
  386. }
  387. /**
  388. * Adds an image to the list of embedded
  389. * images.
  390. *
  391. * @param string $object Embedded image object
  392. */
  393. public function addEmbeddedImage($embeddedImage)
  394. {
  395. $embeddedImage->cid = md5(uniqid(time()));
  396. $this->html_images[] = $embeddedImage;
  397. }
  398. /**
  399. * Adds a file to the list of attachments.
  400. *
  401. * @param string $attachment Attachment object
  402. */
  403. public function addAttachment($attachment)
  404. {
  405. $this->attachments[] = $attachment;
  406. }
  407. /**
  408. * Adds a text subpart to a mime_part object
  409. *
  410. * @param object $obj
  411. * @return object Mime part object
  412. */
  413. private function addTextPart(&$message)
  414. {
  415. $params['content_type'] = 'text/plain';
  416. $params['encoding'] = $this->build_params['text_encoding']->getType();
  417. $params['charset'] = $this->build_params['text_charset'];
  418. if (!empty($message)) {
  419. $message->addSubpart($this->text, $params);
  420. } else {
  421. $message = new Mail_mimePart($this->text, $params);
  422. }
  423. }
  424. /**
  425. * Adds a html subpart to a mime_part object
  426. *
  427. * @param object $obj
  428. * @return object Mime part object
  429. */
  430. private function addHtmlPart(&$message)
  431. {
  432. $params['content_type'] = 'text/html';
  433. $params['encoding'] = $this->build_params['html_encoding']->getType();
  434. $params['charset'] = $this->build_params['html_charset'];
  435. if (!empty($message)) {
  436. $message->addSubpart($this->html, $params);
  437. } else {
  438. $message = new Mail_mimePart($this->html, $params);
  439. }
  440. }
  441. /**
  442. * Starts a message with a mixed part
  443. *
  444. * @return object Mime part object
  445. */
  446. private function addMixedPart(&$message)
  447. {
  448. $params['content_type'] = 'multipart/mixed';
  449. $message = new Mail_mimePart('', $params);
  450. }
  451. /**
  452. * Adds an alternative part to a mime_part object
  453. *
  454. * @param object $obj
  455. * @return object Mime part object
  456. */
  457. private function addAlternativePart(&$message)
  458. {
  459. $params['content_type'] = 'multipart/alternative';
  460. if (!empty($message)) {
  461. return $message->addSubpart('', $params);
  462. } else {
  463. $message = new Mail_mimePart('', $params);
  464. }
  465. }
  466. /**
  467. * Adds a html subpart to a mime_part object
  468. *
  469. * @param object $obj
  470. * @return object Mime part object
  471. */
  472. private function addRelatedPart(&$message)
  473. {
  474. $params['content_type'] = 'multipart/related';
  475. if (!empty($message)) {
  476. return $message->addSubpart('', $params);
  477. } else {
  478. $message = new Mail_mimePart('', $params);
  479. }
  480. }
  481. /**
  482. * Adds all html images to a mime_part object
  483. *
  484. * @param object $obj Message object
  485. */
  486. private function addHtmlImageParts(&$message)
  487. {
  488. foreach ($this->html_images as $value) {
  489. $params['content_type'] = $value->contentType;
  490. $params['encoding'] = $value->encoding->getType();
  491. $params['disposition'] = 'inline';
  492. $params['dfilename'] = $value->name;
  493. $params['cid'] = $value->cid;
  494. $message->addSubpart($value->data, $params);
  495. }
  496. }
  497. /**
  498. * Adds all attachments to a mime_part object
  499. *
  500. * @param object $obj Message object
  501. */
  502. private function addAttachmentParts(&$message)
  503. {
  504. foreach ($this->attachments as $value) {
  505. $params['content_type'] = $value->contentType;
  506. $params['encoding'] = $value->encoding->getType();
  507. $params['disposition'] = 'attachment';
  508. $params['dfilename'] = $value->name;
  509. $message->addSubpart($value->data, $params);
  510. }
  511. }
  512. /**
  513. * Builds the multipart message.
  514. */
  515. private function build()
  516. {
  517. if (!empty($this->html_images)) {
  518. foreach ($this->html_images as $value) {
  519. $quoted = preg_quote($value->name);
  520. $cid = preg_quote($value->cid);
  521. $this->html = preg_replace("#src=\"$quoted\"|src='$quoted'#", "src=\"cid:$cid\"", $this->html);
  522. $this->html = preg_replace("#background=\"$quoted\"|background='$quoted'#", "background=\"cid:$cid\"", $this->html);
  523. }
  524. }
  525. $message = null;
  526. $attachments = !empty($this->attachments);
  527. $html_images = !empty($this->html_images);
  528. $html = !empty($this->html);
  529. $text = !$html;
  530. switch (true) {
  531. case $text:
  532. $message = null;
  533. if ($attachments) {
  534. $this->addMixedPart($message);
  535. }
  536. $this->addTextPart($message);
  537. // Attachments
  538. $this->addAttachmentParts($message);
  539. break;
  540. case $html AND !$attachments AND !$html_images:
  541. $this->addAlternativePart($message);
  542. $this->addTextPart($message);
  543. $this->addHtmlPart($message);
  544. break;
  545. case $html AND !$attachments AND $html_images:
  546. $this->addRelatedPart($message);
  547. $alt = $this->addAlternativePart($message);
  548. $this->addTextPart($alt);
  549. $this->addHtmlPart($alt);
  550. // HTML images
  551. $this->addHtmlImageParts($message);
  552. break;
  553. case $html AND $attachments AND !$html_images:
  554. $this->addMixedPart($message);
  555. $alt = $this->addAlternativePart($message);
  556. $this->addTextPart($alt);
  557. $this->addHtmlPart($alt);
  558. // Attachments
  559. $this->addAttachmentParts($message);
  560. break;
  561. case $html AND $attachments AND $html_images:
  562. $this->addMixedPart($message);
  563. $rel = $this->addRelatedPart($message);
  564. $alt = $this->addAlternativePart($rel);
  565. $this->addTextPart($alt);
  566. $this->addHtmlPart($alt);
  567. // HTML images
  568. $this->addHtmlImageParts($rel);
  569. // Attachments
  570. $this->addAttachmentParts($message);
  571. break;
  572. }
  573. if (isset($message)) {
  574. $output = $message->encode();
  575. $this->output = $output['body'];
  576. $this->headers = array_merge($this->headers, $output['headers']);
  577. // Figure out hostname
  578. if (!empty($_SERVER['HTTP_HOST'])) {
  579. $hostname = $_SERVER['HTTP_HOST'];
  580. } else if (!empty($_SERVER['SERVER_NAME'])) {
  581. $hostname = $_SERVER['SERVER_NAME'];
  582. } else if (!empty($_ENV['HOSTNAME'])) {
  583. $hostname = $_ENV['HOSTNAME'];
  584. } else {
  585. $hostname = 'localhost';
  586. }
  587. $message_id = sprintf('<%s.%s@%s>', base_convert(time(), 10, 36), base_convert(rand(), 10, 36), $hostname);
  588. $this->headers['Message-ID'] = $message_id;
  589. $this->is_built = true;
  590. return true;
  591. } else {
  592. return false;
  593. }
  594. }
  595. /**
  596. * Function to encode a header if necessary
  597. * according to RFC2047
  598. *
  599. * @param string $input Value to encode
  600. * @param string $charset Character set to use
  601. * @return string Encoded value
  602. */
  603. private function encodeHeader($input, $charset = 'ISO-8859-1')
  604. {
  605. preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $input, $matches);
  606. foreach ($matches[1] as $value) {
  607. $replacement = preg_replace('/([\x80-\xFF])/e', '"=" . strtoupper(dechex(ord("\1")))', $value);
  608. $input = str_replace($value, '=?' . $charset . '?Q?' . $replacement . '?=', $input);
  609. }
  610. return $input;
  611. }
  612. /**
  613. * Sends the mail.
  614. *
  615. * @param array $recipients Array of receipients to send the mail to
  616. * @param string $type How to send the mail ('mail' or 'sendmail' or 'smtp')
  617. * @return mixed
  618. */
  619. public function send($recipients, $type = 'mail')
  620. {
  621. if (!defined('CRLF')) {
  622. $this->setCRLF( ($type == 'mail' OR $type == 'sendmail') ? "\n" : "\r\n");
  623. }
  624. if (!$this->is_built) {
  625. $this->build();
  626. }
  627. switch ($type) {
  628. case 'mail':
  629. $subject = '';
  630. if (!empty($this->headers['Subject'])) {
  631. $subject = $this->encodeHeader($this->headers['Subject'], $this->build_params['head_charset']);
  632. unset($this->headers['Subject']);
  633. }
  634. // Get flat representation of headers
  635. foreach ($this->headers as $name => $value) {
  636. $headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
  637. }
  638. $to = $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
  639. if (!empty($this->return_path)) {
  640. $result = mail($to, $subject, $this->output, implode(CRLF, $headers), '-f' . $this->return_path);
  641. } else {
  642. $result = mail($to, $subject, $this->output, implode(CRLF, $headers));
  643. }
  644. // Reset the subject in case mail is resent
  645. if ($subject !== '') {
  646. $this->headers['Subject'] = $subject;
  647. }
  648. // Return
  649. return $result;
  650. break;
  651. case 'sendmail':
  652. // Get flat representation of headers
  653. foreach ($this->headers as $name => $value) {
  654. $headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
  655. }
  656. // Encode To:
  657. $headers[] = 'To: ' . $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
  658. // Get return path arg for sendmail command if necessary
  659. $returnPath = '';
  660. if (!empty($this->return_path)) {
  661. $returnPath = '-f' . $this->return_path;
  662. }
  663. $pipe = popen($this->sendmail_path . " " . $returnPath, 'w');
  664. $bytes = fputs($pipe, implode(CRLF, $headers) . CRLF . CRLF . $this->output);
  665. $r = pclose($pipe);
  666. return $r;
  667. break;
  668. case 'smtp':
  669. require_once(dirname(__FILE__) . '/smtp.php');
  670. require_once(dirname(__FILE__) . '/RFC822.php');
  671. $smtp = &smtp::connect($this->smtp_params);
  672. // Parse recipients argument for internet addresses
  673. foreach ($recipients as $recipient) {
  674. $addresses = Mail_RFC822::parseAddressList($recipient, $this->smtp_params['helo'], null, false);
  675. foreach ($addresses as $address) {
  676. $smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
  677. }
  678. }
  679. unset($addresses); // These are reused
  680. unset($address); // These are reused
  681. // Get flat representation of headers, parsing
  682. // Cc and Bcc as we go
  683. foreach ($this->headers as $name => $value) {
  684. if ($name == 'Cc' OR $name == 'Bcc') {
  685. $addresses = Mail_RFC822::parseAddressList($value, $this->smtp_params['helo'], null, false);
  686. foreach ($addresses as $address) {
  687. $smtp_recipients[] = sprintf('%s@%s', $address->mailbox, $address->host);
  688. }
  689. }
  690. if ($name == 'Bcc') {
  691. continue;
  692. }
  693. $headers[] = $name . ': ' . $this->encodeHeader($value, $this->build_params['head_charset']);
  694. }
  695. // Add To header based on $recipients argument
  696. $headers[] = 'To: ' . $this->encodeHeader(implode(', ', $recipients), $this->build_params['head_charset']);
  697. // Add headers to send_params
  698. $send_params['headers'] = $headers;
  699. $send_params['recipients'] = array_values(array_unique($smtp_recipients));
  700. $send_params['body'] = $this->output;
  701. // Setup return path
  702. if (isset($this->return_path)) {
  703. $send_params['from'] = $this->return_path;
  704. } elseif (!empty($this->headers['From'])) {
  705. $from = Mail_RFC822::parseAddressList($this->headers['From']);
  706. $send_params['from'] = sprintf('%s@%s', $from[0]->mailbox, $from[0]->host);
  707. } else {
  708. $send_params['from'] = 'postmaster@' . $this->smtp_params['helo'];
  709. }
  710. // Send it
  711. if (!$smtp->send($send_params)) {
  712. $this->errors = $smtp->getErrors();
  713. return false;
  714. }
  715. return true;
  716. break;
  717. }
  718. }
  719. /**
  720. * Use this method to return the email
  721. * in message/rfc822 format. Useful for
  722. * adding an email to another email as
  723. * an attachment. there's a commented
  724. * out example in example.php.
  725. *
  726. * @param array $recipients Array of recipients
  727. * @param string $type Method to be used to send the mail.
  728. * Used to determine the line ending type.
  729. */
  730. public function getRFC822($recipients, $type = 'mail')
  731. {
  732. // Make up the date header as according to RFC822
  733. $this->setHeader('Date', date('D, d M y H:i:s O'));
  734. if (!defined('CRLF')) {
  735. $this->setCRLF($type == 'mail' ? "\n" : "\r\n");
  736. }
  737. if (!$this->is_built) {
  738. $this->build();
  739. }
  740. // Return path ?
  741. if (isset($this->return_path)) {
  742. $headers[] = 'Return-Path: ' . $this->return_path;
  743. }
  744. // Get flat representation of headers
  745. foreach ($this->headers as $name => $value) {
  746. $headers[] = $name . ': ' . $value;
  747. }
  748. $headers[] = 'To: ' . implode(', ', $recipients);
  749. return implode(CRLF, $headers) . CRLF . CRLF . $this->output;
  750. }
  751. } // End of class.
  752. /**
  753. * Attachment classes
  754. */
  755. class attachment
  756. {
  757. /**
  758. * Data of attachment
  759. * @var string
  760. */
  761. public $data;
  762. /**
  763. * Name of attachment (filename)
  764. * @var string
  765. */
  766. public $name;
  767. /**
  768. * Content type of attachment
  769. * @var string
  770. */
  771. public $contentType;
  772. /**
  773. * Encoding type of attachment
  774. * @var object
  775. */
  776. public $encoding;
  777. /**
  778. * Constructor
  779. *
  780. * @param string $data File data
  781. * @param string $name Name of attachment (filename)
  782. * @param string $contentType Content type of attachment
  783. * @param object $encoding Encoding type to use
  784. */
  785. public function __construct($data, $name, $contentType, iEncoding $encoding)
  786. {
  787. $this->data = $data;
  788. $this->name = $name;
  789. $this->contentType = $contentType;
  790. $this->encoding = $encoding;
  791. }
  792. }
  793. /**
  794. * File based attachment class
  795. */
  796. class fileAttachment extends attachment
  797. {
  798. /**
  799. * Constructor
  800. *
  801. * @param string $filename Name of file
  802. * @param string $contentType Content type of file
  803. * @param string $encoding What encoding to use
  804. */
  805. public function __construct($filename, $contentType = 'application/octet-stream', $encoding = null)
  806. {
  807. $encoding = is_null($encoding) ? new Base64Encoding() : $encoding;
  808. parent::__construct(file_get_contents($filename), basename($filename), $contentType, $encoding);
  809. }
  810. }
  811. /**
  812. * Attachment class to handle attachments which are contained
  813. * in a variable.
  814. */
  815. class stringAttachment extends attachment
  816. {
  817. /**
  818. * Constructor
  819. *
  820. * @param string $data File data
  821. * @param string $name Name of attachment (filename)
  822. * @param string $contentType Content type of file
  823. * @param string $encoding What encoding to use
  824. */
  825. public function __construct($data, $name = '', $contentType = 'application/octet-stream', $encoding = null)
  826. {
  827. $encoding = is_null($encoding) ? new Base64Encoding() : $encoding;
  828. parent::__construct($data, $name, $contentType, $encoding);
  829. }
  830. }
  831. /**
  832. * File based embedded image class
  833. */
  834. class fileEmbeddedImage extends fileAttachment
  835. {
  836. }
  837. /**
  838. * String based embedded image class
  839. */
  840. class stringEmbeddedImage extends stringAttachment
  841. {
  842. }
  843. /**
  844. *
  845. */
  846. /**
  847. * Encoding interface
  848. */
  849. interface iEncoding
  850. {
  851. public function encode($input);
  852. public function getType();
  853. }
  854. /**
  855. * Base64 Encoding class
  856. */
  857. class Base64Encoding implements iEncoding
  858. {
  859. /*
  860. * Function to encode data using
  861. * base64 encoding.
  862. *
  863. * @param string $input Data to encode
  864. */
  865. public function encode($input)
  866. {
  867. return rtrim(chunk_split(base64_encode($input), 76, defined('MAIL_MIME_PART_CRLF') ? MAIL_MIME_PART_CRLF : "\r\n"));
  868. }
  869. /**
  870. * Returns type
  871. */
  872. public function getType()
  873. {
  874. return 'base64';
  875. }
  876. }
  877. /**
  878. * Quoted Printable Encoding class
  879. */
  880. class QPrintEncoding implements iEncoding
  881. {
  882. /*
  883. * Function to encode data using
  884. * quoted-printable encoding.
  885. *
  886. * @param string $input Data to encode
  887. */
  888. public function encode($input)
  889. {
  890. // Replace non printables
  891. $input = preg_replace('/([^\x20\x21-\x3C\x3E-\x7E\x0A\x0D])/e', 'sprintf("=%02X", ord("\1"))', $input);
  892. $inputLen = strlen($input);
  893. $outLines = array();
  894. $output = '';
  895. $lines = preg_split('/\r?\n/', $input);
  896. // Walk through each line
  897. for ($i=0; $i<count($lines); $i++) {
  898. // Is line too long ?
  899. if (strlen($lines[$i]) > $lineMax) {
  900. $outLines[] = substr($lines[$i], 0, $lineMax - 1) . "="; // \r\n Gets added when lines are imploded
  901. $lines[$i] = substr($lines[$i], $lineMax - 1);
  902. $i--; // Ensure this line gets redone as we just changed it
  903. } else {
  904. $outLines[] = $lines[$i];
  905. }
  906. }
  907. // Convert trailing whitespace
  908. $output = preg_replace('/(\x20+)$/me', 'str_replace(" ", "=20", "\1")', $outLines);
  909. return implode("\r\n", $output);
  910. }
  911. /**
  912. * Returns type
  913. */
  914. public function getType()
  915. {
  916. return 'quoted-printable';
  917. }
  918. }
  919. /**
  920. * 7Bit Encoding class
  921. */
  922. class SevenBitEncoding implements iEncoding
  923. {
  924. /*
  925. * Function to "encode" data using
  926. * 7bit encoding.
  927. *
  928. * @param string $input Data to encode
  929. */
  930. public function encode($input)
  931. {
  932. return $input;
  933. }
  934. /**
  935. * Returns type
  936. */
  937. public function getType()
  938. {
  939. return '7bit';
  940. }
  941. }
  942. /**
  943. * 8Bit Encoding class
  944. */
  945. class EightBitEncoding implements iEncoding
  946. {
  947. /*
  948. * Function to "encode" data using
  949. * 8bit encoding.
  950. *
  951. * @param string $input Data to encode
  952. */
  953. public function encode($input)
  954. {
  955. return $input;
  956. }
  957. /**
  958. * Returns type
  959. */
  960. public function getType()
  961. {
  962. return '8bit';
  963. }
  964. }
  965. ?>