PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/phplist/admin/class.html.mime.mail-outlookfix.inc

https://github.com/radicaldesigns/amp
PHP | 632 lines | 321 code | 121 blank | 190 comment | 49 complexity | 584a5e10c67ecca1a2dc00ff9944c5f8 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, BSD-3-Clause, LGPL-2.0, CC-BY-SA-3.0, AGPL-1.0
  1. <?php
  2. require_once dirname(__FILE__).'/accesscheck.php';
  3. /***************************************
  4. ** Title.........: HTML Mime Mail class
  5. ** Version.......: 2.0.3
  6. ** Author........: Richard Heyes <richard@phpguru.org>
  7. ** Filename......: class.html.mime.mail.class
  8. ** Last changed..: 21 December 2001
  9. ** License.......: Free to use. If you find it useful
  10. ** though, feel free to buy me something
  11. ** from my wishlist :)
  12. ** http://www.amazon.co.uk/exec/obidos/wishlist/S8H2UOGMPZK6
  13. ** Modified for use with PHPlist
  14. ** Modification...: 3 April 2002
  15. ** Modified by....: Michiel Dethmers
  16. ***************************************/
  17. require_once($GLOBALS["coderoot"].'mimePart.php');
  18. class html_mime_mail{
  19. var $html;
  20. var $text;
  21. var $output;
  22. var $html_text;
  23. var $html_images;
  24. var $image_types;
  25. var $build_params;
  26. var $attachments;
  27. var $headers;
  28. /***************************************
  29. ** Constructor function. Sets the headers
  30. ** if supplied.
  31. ***************************************/
  32. function html_mime_mail($headers = array()){
  33. /***************************************
  34. ** Make sure this is defined. This should
  35. ** be \r\n, but due to many people having
  36. ** trouble with that, it is by default \n
  37. ** If you leave it as is, you will be breaking
  38. ** quite a few standards.
  39. ***************************************/
  40. if(!defined('CRLF'))
  41. define('CRLF', "\n", TRUE);
  42. /***************************************
  43. ** Initialise some variables.
  44. ***************************************/
  45. $this->html_images = array();
  46. $this->headers = array();
  47. /***************************************
  48. ** If you want the auto load functionality
  49. ** to find other image/file types, add the
  50. ** extension and content type here.
  51. ***************************************/
  52. $this->image_types = array(
  53. 'gif' => 'image/gif',
  54. 'jpg' => 'image/jpeg',
  55. 'jpeg' => 'image/jpeg',
  56. 'jpe' => 'image/jpeg',
  57. 'bmp' => 'image/bmp',
  58. 'png' => 'image/png',
  59. 'tif' => 'image/tiff',
  60. 'tiff' => 'image/tiff',
  61. 'swf' => 'application/x-shockwave-flash'
  62. );
  63. /***************************************
  64. ** Set these up
  65. ***************************************/
  66. $this->build_params['html_encoding'] = 'quoted-printable';
  67. $this->build_params['text_encoding'] = '7bit';
  68. $this->build_params['html_charset'] = 'iso-8859-1';
  69. $this->build_params['text_charset'] = 'iso-8859-1';
  70. $this->build_params['text_wrap'] = 998;
  71. /***************************************
  72. ** Make sure the MIME version header is first.
  73. ***************************************/
  74. $this->headers[] = 'MIME-Version: 1.0';
  75. foreach($headers as $value){
  76. if(!empty($value))
  77. $this->headers[] = $value;
  78. }
  79. }
  80. /***************************************
  81. ** This function will read a file in
  82. ** from a supplied filename and return
  83. ** it. This can then be given as the first
  84. ** argument of the the functions
  85. ** add_html_image() or add_attachment().
  86. ***************************************/
  87. function get_file_original($filename){
  88. $return = '';
  89. if($fp = fopen($filename, 'rb')){
  90. while(!feof($fp)){
  91. $return .= fread($fp, 1024);
  92. }
  93. fclose($fp);
  94. return $return;
  95. }else{
  96. return FALSE;
  97. }
  98. }
  99. function get_file($templateid,$filename){
  100. global $tables;
  101. $req = Sql_Fetch_Row_Query(sprintf('select data from %s where template = %d and filename = "%s"',
  102. $tables["templateimage"],$templateid,$filename));
  103. return base64_decode($req[0]);
  104. }
  105. /***************************************
  106. ** Function for extracting images from
  107. ** html source. This function will look
  108. ** through the html code supplied by add_html()
  109. ** and find any file that ends in one of the
  110. ** extensions defined in $obj->image_types.
  111. ** If the file exists it will read it in and
  112. ** embed it, (not an attachment).
  113. **
  114. ** Function contributed by Dan Allen
  115. ***************************************/
  116. function find_html_images_original($images_dir) {
  117. // Build the list of image extensions
  118. while(list($key,) = each($this->image_types))
  119. $extensions[] = $key;
  120. preg_match_all('/"([^"]+\.('.implode('|', $extensions).'))"/Ui', $this->html, $images);
  121. for($i=0; $i<count($images[1]); $i++){
  122. if(file_exists($images_dir.$images[1][$i])){
  123. $html_images[] = $images[1][$i];
  124. $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
  125. }
  126. }
  127. if(!empty($html_images)){
  128. // If duplicate images are embedded, they may show up as attachments, so remove them.
  129. $html_images = array_unique($html_images);
  130. sort($html_images);
  131. for($i=0; $i<count($html_images); $i++){
  132. if($image = $this->get_file($images_dir.$html_images[$i])){
  133. $content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
  134. $this->add_html_image($image, basename($html_images[$i]), $content_type);
  135. }
  136. }
  137. }
  138. }
  139. function image_exists($templateid,$filename) {
  140. global $tables;
  141. $req = Sql_Query(sprintf('select * from %s where template = %d and filename = "%s"',
  142. $tables["templateimage"],$templateid,$filename));
  143. return Sql_Affected_Rows();
  144. }
  145. function find_html_images($templateid) {
  146. // Build the list of image extensions
  147. while(list($key,) = each($this->image_types))
  148. $extensions[] = $key;
  149. preg_match_all('/"([^"]+\.('.implode('|', $extensions).'))"/Ui', $this->html, $images);
  150. for($i=0; $i<count($images[1]); $i++){
  151. if($this->image_exists($templateid,$images[1][$i])){
  152. $html_images[] = $images[1][$i];
  153. $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
  154. }
  155. }
  156. if(!empty($html_images)){
  157. // If duplicate images are embedded, they may show up as attachments, so remove them.
  158. $html_images = array_unique($html_images);
  159. sort($html_images);
  160. for($i=0; $i<count($html_images); $i++){
  161. if($image = $this->get_file($templateid,$html_images[$i])){
  162. $content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
  163. $this->add_html_image($image, basename($html_images[$i]), $content_type);
  164. }
  165. }
  166. }
  167. }
  168. /***************************************
  169. ** Adds plain text. Use this function
  170. ** when NOT sending html email
  171. ***************************************/
  172. function add_text($text = ''){
  173. $this->text = $text;
  174. }
  175. function append_text($text = ''){
  176. $this->text .= "\n".$text;
  177. }
  178. /***************************************
  179. ** Adds a html part to the mail.
  180. ** Also replaces image names with
  181. ** content-id's.
  182. ***************************************/
  183. function add_html($html, $text = NULL, $templateid = 0){
  184. $this->html = $html;
  185. $this->html_text = $text;
  186. # if(isset($images_dir))
  187. $this->find_html_images($templateid);
  188. }
  189. /***************************************
  190. ** Adds an image to the list of embedded
  191. ** images.
  192. ***************************************/
  193. function add_html_image($file, $name = '', $c_type='application/octet-stream'){
  194. $this->html_images[] = array(
  195. 'body' => $file,
  196. 'name' => $name,
  197. 'c_type' => $c_type,
  198. 'cid' => md5(uniqid(time()))
  199. );
  200. }
  201. /***************************************
  202. ** Adds a PDF to the list of embedded
  203. ** pdfs.
  204. ***************************************/
  205. function add_pdf($file, $name = '', $c_type='application/pdf'){
  206. $this->html_images[] = array(
  207. 'body' => $file,
  208. 'name' => $name,
  209. 'c_type' => $c_type,
  210. 'cid' => md5(uniqid(time()))
  211. );
  212. }
  213. /***************************************
  214. ** Adds a file to the list of attachments.
  215. ***************************************/
  216. function add_attachment($file, $name = '', $c_type='application/octet-stream', $encoding = 'base64'){
  217. $this->attachments[] = array(
  218. 'body' => $file,
  219. 'name' => $name,
  220. 'c_type' => $c_type,
  221. 'encoding' => $encoding
  222. );
  223. }
  224. /***************************************
  225. ** Adds a text subpart to a mime_part object
  226. ***************************************/
  227. function &add_text_part(&$obj, $text){
  228. $params['content_type'] = 'text/plain';
  229. $params['encoding'] = $this->build_params['text_encoding'];
  230. $params['charset'] = $this->build_params['text_charset'];
  231. if(is_object($obj)){
  232. return $obj->addSubpart($text, $params);
  233. }else{
  234. return new Mail_mimePart($text, $params);
  235. }
  236. }
  237. /***************************************
  238. ** Adds a html subpart to a mime_part object
  239. ***************************************/
  240. function &add_html_part(&$obj){
  241. $params['content_type'] = 'text/html';
  242. $params['encoding'] = $this->build_params['html_encoding'];
  243. $params['charset'] = $this->build_params['html_charset'];
  244. if(is_object($obj)){
  245. return $obj->addSubpart($this->html, $params);
  246. }else{
  247. return new Mail_mimePart($this->html, $params);
  248. }
  249. }
  250. /***************************************
  251. ** Starts a message with a mixed part
  252. ***************************************/
  253. function &add_mixed_part(){
  254. $params['content_type'] = 'multipart/mixed';
  255. return new Mail_mimePart('', $params);
  256. }
  257. /***************************************
  258. ** Adds an alternative part to a mime_part object
  259. ***************************************/
  260. function &add_alternative_part(&$obj){
  261. $params['content_type'] = 'multipart/alternative';
  262. if(is_object($obj)){
  263. return $obj->addSubpart('', $params);
  264. }else{
  265. return new Mail_mimePart('', $params);
  266. }
  267. }
  268. /***************************************
  269. ** Adds a html subpart to a mime_part object
  270. ***************************************/
  271. function &add_related_part(&$obj){
  272. $params['content_type'] = 'multipart/related';
  273. # js 3-5-04 $params['content_type'] = 'multipart/alternative';
  274. if(is_object($obj)){
  275. return $obj->addSubpart('', $params);
  276. }else{
  277. return new Mail_mimePart('', $params);
  278. }
  279. }
  280. /***************************************
  281. ** Adds an html image subpart to a mime_part object
  282. ***************************************/
  283. function &add_html_image_part(&$obj, $value){
  284. $params['content_type'] = $value['c_type'];
  285. $params['encoding'] = 'base64';
  286. $params['disposition'] = 'inline';
  287. $params['dfilename'] = $value['name'];
  288. $params['cid'] = $value['cid'];
  289. $obj->addSubpart($value['body'], $params);
  290. }
  291. /***************************************
  292. ** Adds an attachment subpart to a mime_part object
  293. ***************************************/
  294. function &add_attachment_part(&$obj, $value){
  295. $params['content_type'] = $value['c_type'];
  296. $params['encoding'] = $value['encoding'];
  297. $params['disposition'] = 'attachment';
  298. $params['dfilename'] = $value['name'];
  299. $obj->addSubpart($value['body'], $params);
  300. }
  301. /***************************************
  302. ** Builds the multipart message from the
  303. ** list ($this->_parts). $params is an
  304. ** array of parameters that shape the building
  305. ** of the message. Currently supported are:
  306. **
  307. ** $params['html_encoding'] - The type of encoding to use on html. Valid options are
  308. ** "7bit", "quoted-printable" or "base64" (all without quotes).
  309. ** 7bit is EXPRESSLY NOT RECOMMENDED. Default is quoted-printable
  310. ** $params['text_encoding'] - The type of encoding to use on plain text Valid options are
  311. ** "7bit", "quoted-printable" or "base64" (all without quotes).
  312. ** Default is 7bit
  313. ** $params['text_wrap'] - The character count at which to wrap 7bit encoded data.
  314. ** Default this is 998.
  315. ** $params['html_charset'] - The character set to use for a html section.
  316. ** Default is iso-8859-1
  317. ** $params['text_charset'] - The character set to use for a text section.
  318. ** - Default is iso-8859-1
  319. ***************************************/
  320. function build_message($params = array()){
  321. if(count($params) > 0)
  322. while(list($key, $value) = each($params))
  323. $this->build_params[$key] = $value;
  324. if(!empty($this->html_images))
  325. foreach($this->html_images as $value)
  326. $this->html = str_replace('"'.$value['name'].'"', '"cid:'.$value['cid'].'"', $this->html);
  327. $null = NULL;
  328. $attachments = !empty($this->attachments) ? TRUE : FALSE;
  329. $html_images = !empty($this->html_images) ? TRUE : FALSE;
  330. $html = !empty($this->html) ? TRUE : FALSE;
  331. $text = isset($this->text) ? TRUE : FALSE;
  332. switch(TRUE){
  333. case $text AND !$attachments:
  334. $message = $this->add_text_part($null, $this->text);
  335. break;
  336. case !$text AND $attachments AND !$html:
  337. $message = $this->add_mixed_part();
  338. for($i=0; $i<count($this->attachments); $i++)
  339. $this->add_attachment_part($message, $this->attachments[$i]);
  340. break;
  341. case $text AND $attachments:
  342. $message = $this->add_mixed_part();
  343. $this->add_text_part($message, $this->text);
  344. for($i=0; $i<count($this->attachments); $i++)
  345. $this->add_attachment_part($message, $this->attachments[$i]);
  346. break;
  347. case $html AND !$attachments AND !$html_images:
  348. if(!is_null($this->html_text)){
  349. $message = $this->add_alternative_part($null);
  350. $this->add_text_part($message, $this->html_text);
  351. $this->add_html_part($message);
  352. }else{
  353. $message = $this->add_html_part($null);
  354. }
  355. break;
  356. # case $html AND !$attachments AND $html_images:
  357. # if(!is_null($this->html_text)){
  358. # $message = $this->add_alternative_part($null);
  359. # $this->add_text_part($message, $this->html_text);
  360. # $related = $this->add_related_part($message);
  361. # }else{
  362. # $message = $this->add_related_part($null);
  363. # $related = $message;
  364. # }
  365. # $this->add_html_part($related);
  366. # for($i=0; $i<count($this->html_images); $i++)
  367. # $this->add_html_image_part($related, $this->html_images[$i]);
  368. # break;
  369. #
  370. # The Above lines are as I found them
  371. # changed by <stormesj@yahoo.com>
  372. # The following are as I think it should be for MS Outlook,
  373. # This may and probibly will break outher email clients.
  374. #
  375. case $html AND !$attachments AND $html_images:
  376. $message = $this->add_alternative_part($null);
  377. $this->add_text_part($message, $this->html_text);
  378. $related = $this->add_html_part($message);
  379. for($i=0; $i<count($this->html_images); $i++)
  380. $this->add_html_image_part($message, $this->html_images[$i]);
  381. break;
  382. case $html AND $attachments AND !$html_images:
  383. $message = $this->add_mixed_part();
  384. if(!is_null($this->html_text)){
  385. $alt = $this->add_alternative_part($message);
  386. $this->add_text_part($alt, $this->html_text);
  387. $this->add_html_part($alt);
  388. }else{
  389. $this->add_html_part($message);
  390. }
  391. for($i=0; $i<count($this->attachments); $i++)
  392. $this->add_attachment_part($message, $this->attachments[$i]);
  393. break;
  394. # The following is broken with MS Outlook don't use,
  395. # see case $html AND !$attachments AND $html_images:
  396. # James Stormes 03-05-04 <jstormes@yahoo.com>
  397. #
  398. # case $html AND $attachments AND $html_images:
  399. # $message = $this->add_mixed_part();
  400. # if(!is_null($this->html_text)){
  401. # $alt = $this->add_alternative_part($message);
  402. # $rel = $this->add_related_part($alt);
  403. # }else{
  404. # $rel = $this->add_related_part($message);
  405. # }
  406. # $this->add_html_part($rel);
  407. # for($i=0; $i<count($this->html_images); $i++)
  408. # $this->add_html_image_part($rel, $this->html_images[$i]);
  409. # for($i=0; $i<count($this->attachments); $i++)
  410. # $this->add_attachment_part($message, $this->attachments[$i]);
  411. # break;
  412. }
  413. if(isset($message)){
  414. $output = $message->encode();
  415. $this->output = $output['body'];
  416. foreach($output['headers'] as $key => $value){
  417. $headers[] = $key.': '.$value;
  418. }
  419. $this->headers = array_merge($this->headers, $headers);
  420. return TRUE;
  421. }else
  422. return FALSE;
  423. }
  424. /***************************************
  425. ** Sends the mail.
  426. ***************************************/
  427. function send($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = ''){
  428. $to = ($to_name != '') ? '"'.$to_name.'" <'.$to_addr.'>' : $to_addr;
  429. $from = ($from_name != '') ? '"'.$from_name.'" <'.$from_addr.'>' : $from_addr;
  430. if(is_string($headers))
  431. $headers = explode(CRLF, trim($headers));
  432. for($i=0; $i<count($headers); $i++){
  433. if(is_array($headers[$i]))
  434. for($j=0; $j<count($headers[$i]); $j++)
  435. if($headers[$i][$j] != '')
  436. $xtra_headers[] = $headers[$i][$j];
  437. if($headers[$i] != '')
  438. $xtra_headers[] = $headers[$i];
  439. }
  440. if(!isset($xtra_headers))
  441. $xtra_headers = array();
  442. return sendMail($to, $subject, $this->output, 'From: '.$from.CRLF.implode(CRLF, $this->headers).CRLF.implode(CRLF, $xtra_headers));
  443. }
  444. /***************************************
  445. ** Use this method to deliver using direct
  446. ** smtp connection. Relies upon the smtp
  447. ** class available from http://www.heyes-computing.net
  448. ** You probably downloaded it with this class though.
  449. **
  450. ** bool smtp_send(
  451. ** object The smtp object,
  452. ** array Parameters to pass to the smtp object
  453. ** See example.1.php for details.
  454. ** )
  455. ***************************************/
  456. function smtp_send(&$smtp, $params = array()){
  457. foreach($params as $key => $value){
  458. switch($key){
  459. case 'headers':
  460. $headers = $value;
  461. break;
  462. case 'from':
  463. $send_params['from'] = $value;
  464. break;
  465. case 'recipients':
  466. $send_params['recipients'] = $value;
  467. break;
  468. }
  469. }
  470. $send_params['body'] = $this->output;
  471. $send_params['headers'] = array_merge($this->headers, $headers);
  472. return $smtp->send($send_params);
  473. }
  474. /***************************************
  475. ** Use this method to return the email
  476. ** in message/rfc822 format. Useful for
  477. ** adding an email to another email as
  478. ** an attachment. there's a commented
  479. ** out example in example.php.
  480. **
  481. ** string get_rfc822(string To name,
  482. ** string To email,
  483. ** string From name,
  484. ** string From email,
  485. ** [string Subject,
  486. ** string Extra headers])
  487. ***************************************/
  488. function get_rfc822($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = ''){
  489. // Make up the date header as according to RFC822
  490. $date = 'Date: '.date('D, d M y H:i:s');
  491. $to = ($to_name != '') ? 'To: "'.$to_name.'" <'.$to_addr.'>' : 'To: '.$to_addr;
  492. $from = ($from_name != '') ? 'From: "'.$from_name.'" <'.$from_addr.'>' : 'From: '.$from_addr;
  493. if(is_string($subject))
  494. $subject = 'Subject: '.$subject;
  495. if(is_string($headers))
  496. $headers = explode(CRLF, trim($headers));
  497. for($i=0; $i<count($headers); $i++){
  498. if(is_array($headers[$i]))
  499. for($j=0; $j<count($headers[$i]); $j++)
  500. if($headers[$i][$j] != '')
  501. $xtra_headers[] = $headers[$i][$j];
  502. if($headers[$i] != '')
  503. $xtra_headers[] = $headers[$i];
  504. }
  505. if(!isset($xtra_headers))
  506. $xtra_headers = array();
  507. $headers = array_merge($this->headers, $xtra_headers);
  508. return $date.CRLF.$from.CRLF.$to.CRLF.$subject.CRLF.implode(CRLF, $headers).CRLF.CRLF.$this->output;
  509. }
  510. } // End of class.
  511. ?>