Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
8.9KB

  1. <?php
  2. require_once('include/html2plain.php');
  3. require_once('include/msgclean.php');
  4. require_once('include/quoteconvert.php');
  5. function email_connect($mailbox,$username,$password) {
  6. if (! function_exists('imap_open'))
  7. return false;
  8. $mbox = @imap_open($mailbox,$username,$password);
  9. return $mbox;
  10. }
  11. function email_poll($mbox,$email_addr) {
  12. if (! ($mbox && $email_addr))
  13. return array();
  14. $search1 = @imap_search($mbox,'FROM "' . $email_addr . '"', SE_UID);
  15. if (! $search1)
  16. $search1 = array();
  17. $search2 = @imap_search($mbox,'TO "' . $email_addr . '"', SE_UID);
  18. if (! $search2)
  19. $search2 = array();
  20. $search3 = @imap_search($mbox,'CC "' . $email_addr . '"', SE_UID);
  21. if (! $search3)
  22. $search3 = array();
  23. $search4 = @imap_search($mbox,'BCC "' . $email_addr . '"', SE_UID);
  24. if (! $search4)
  25. $search4 = array();
  26. $res = array_unique(array_merge($search1,$search2,$search3,$search4));
  27. return $res;
  28. }
  29. function construct_mailbox_name($mailacct) {
  30. $ret = '{' . $mailacct['server'] . ((intval($mailacct['port'])) ? ':' . $mailacct['port'] : '');
  31. $ret .= (($mailacct['ssltype']) ? '/' . $mailacct['ssltype'] . '/novalidate-cert' : '');
  32. $ret .= '}' . $mailacct['mailbox'];
  33. return $ret;
  34. }
  35. function email_msg_meta($mbox,$uid) {
  36. $ret = (($mbox && $uid) ? @imap_fetch_overview($mbox,$uid,FT_UID) : array(array())); // POSSIBLE CLEANUP --> array(array()) is probably redundant now
  37. return ((count($ret)) ? $ret : array());
  38. }
  39. function email_msg_headers($mbox,$uid) {
  40. $raw_header = (($mbox && $uid) ? @imap_fetchheader($mbox,$uid,FT_UID) : '');
  41. $raw_header = str_replace("\r",'',$raw_header);
  42. $ret = array();
  43. $h = explode("\n",$raw_header);
  44. if (count($h))
  45. foreach ($h as $line ) {
  46. if (preg_match("/^[a-zA-Z]/", $line)) {
  47. $key = substr($line,0,strpos($line,':'));
  48. $value = substr($line,strpos($line,':')+1);
  49. $last_entry = strtolower($key);
  50. $ret[$last_entry] = trim($value);
  51. }
  52. else {
  53. $ret[$last_entry] .= ' ' . trim($line);
  54. }
  55. }
  56. return $ret;
  57. }
  58. function email_get_msg($mbox,$uid, $reply) {
  59. $ret = array();
  60. $struc = (($mbox && $uid) ? @imap_fetchstructure($mbox,$uid,FT_UID) : null);
  61. if (! $struc)
  62. return $ret;
  63. if (! $struc->parts) {
  64. $ret['body'] = email_get_part($mbox,$uid,$struc,0, 'html');
  65. $html = $ret['body'];
  66. if (trim($ret['body']) == '')
  67. $ret['body'] = email_get_part($mbox,$uid,$struc,0, 'plain');
  68. else
  69. $ret['body'] = html2bbcode($ret['body']);
  70. }
  71. else {
  72. $text = '';
  73. $html = '';
  74. foreach ($struc->parts as $ptop => $p) {
  75. $x = email_get_part($mbox,$uid,$p,$ptop + 1, 'plain');
  76. if ($x) {
  77. $text .= $x;
  78. }
  79. $x = email_get_part($mbox,$uid,$p,$ptop + 1, 'html');
  80. if ($x) {
  81. $html .= $x;
  82. }
  83. }
  84. if (trim($html) != '') {
  85. $ret['body'] = html2bbcode($html);
  86. } else {
  87. $ret['body'] = $text;
  88. }
  89. }
  90. $ret['body'] = removegpg($ret['body']);
  91. $msg = removesig($ret['body']);
  92. $ret['body'] = $msg['body'];
  93. $ret['body'] = convertquote($ret['body'], $reply);
  94. if (trim($html) != '') {
  95. $ret['body'] = removelinebreak($ret['body']);
  96. }
  97. $ret['body'] = unifyattributionline($ret['body']);
  98. return $ret;
  99. }
  100. // At the moment - only return plain/text.
  101. // Later we'll repackage inline images as data url's and make the HTML safe
  102. function email_get_part($mbox,$uid,$p,$partno, $subtype) {
  103. // $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple
  104. global $htmlmsg,$plainmsg,$charset,$attachments;
  105. //echo $partno."\n";
  106. // DECODE DATA
  107. $data = ($partno)
  108. ? @imap_fetchbody($mbox,$uid,$partno, FT_UID|FT_PEEK)
  109. : @imap_body($mbox,$uid,FT_UID|FT_PEEK);
  110. // Any part may be encoded, even plain text messages, so check everything.
  111. if ($p->encoding==4)
  112. $data = quoted_printable_decode($data);
  113. elseif ($p->encoding==3)
  114. $data = base64_decode($data);
  115. // PARAMETERS
  116. // get all parameters, like charset, filenames of attachments, etc.
  117. $params = array();
  118. if ($p->parameters)
  119. foreach ($p->parameters as $x)
  120. $params[strtolower($x->attribute)] = $x->value;
  121. if (isset($p->dparameters) && $p->dparameters)
  122. foreach ($p->dparameters as $x)
  123. $params[strtolower($x->attribute)] = $x->value;
  124. // ATTACHMENT
  125. // Any part with a filename is an attachment,
  126. // so an attached text file (type 0) is not mistaken as the message.
  127. if ((isset($params['filename']) && $params['filename']) || (isset($params['name']) && $params['name'])) {
  128. // filename may be given as 'Filename' or 'Name' or both
  129. $filename = ($params['filename'])? $params['filename'] : $params['name'];
  130. // filename may be encoded, so see imap_mime_header_decode()
  131. $attachments[$filename] = $data; // this is a problem if two files have same name
  132. }
  133. // TEXT
  134. if ($p->type == 0 && $data) {
  135. // Messages may be split in different parts because of inline attachments,
  136. // so append parts together with blank row.
  137. if (strtolower($p->subtype)==$subtype) {
  138. $data = iconv($params['charset'], 'UTF-8//IGNORE', $data);
  139. return (trim($data) ."\n\n");
  140. } else
  141. $data = '';
  142. // $htmlmsg .= $data ."<br><br>";
  143. $charset = $params['charset']; // assume all parts are same charset
  144. }
  145. // EMBEDDED MESSAGE
  146. // Many bounce notifications embed the original message as type 2,
  147. // but AOL uses type 1 (multipart), which is not handled here.
  148. // There are no PHP functions to parse embedded messages,
  149. // so this just appends the raw source to the main message.
  150. // elseif ($p->type==2 && $data) {
  151. // $plainmsg .= $data."\n\n";
  152. // }
  153. // SUBPART RECURSION
  154. if (isset($p->parts) && $p->parts) {
  155. $x = "";
  156. foreach ($p->parts as $partno0=>$p2) {
  157. $x .= email_get_part($mbox,$uid,$p2,$partno . '.' . ($partno0+1), $subtype); // 1.2, 1.2.1, etc.
  158. //if ($x) {
  159. // return $x;
  160. //}
  161. }
  162. return $x;
  163. }
  164. }
  165. function email_header_encode($in_str, $charset) {
  166. $out_str = $in_str;
  167. $need_to_convert = false;
  168. for ($x = 0; $x < strlen($in_str); $x ++) {
  169. if ((ord($in_str[$x]) == 0) || ((ord($in_str[$x]) > 128))) {
  170. $need_to_convert = true;
  171. }
  172. }
  173. if (! $need_to_convert)
  174. return $in_str;
  175. if ($out_str && $charset) {
  176. // define start delimimter, end delimiter and spacer
  177. $end = "?=";
  178. $start = "=?" . $charset . "?B?";
  179. $spacer = $end . "\r\n " . $start;
  180. // determine length of encoded text within chunks
  181. // and ensure length is even
  182. $length = 75 - strlen($start) - strlen($end);
  183. /*
  184. [EDIT BY danbrown AT php DOT net: The following
  185. is a bugfix provided by (gardan AT gmx DOT de)
  186. on 31-MAR-2005 with the following note:
  187. "This means: $length should not be even,
  188. but divisible by 4. The reason is that in
  189. base64-encoding 3 8-bit-chars are represented
  190. by 4 6-bit-chars. These 4 chars must not be
  191. split between two encoded words, according
  192. to RFC-2047.
  193. */
  194. $length = $length - ($length % 4);
  195. // encode the string and split it into chunks
  196. // with spacers after each chunk
  197. $out_str = base64_encode($out_str);
  198. $out_str = chunk_split($out_str, $length, $spacer);
  199. // remove trailing spacer and
  200. // add start and end delimiters
  201. $spacer = preg_quote($spacer,'/');
  202. $out_str = preg_replace("/" . $spacer . "$/", "", $out_str);
  203. $out_str = $start . $out_str . $end;
  204. }
  205. return $out_str;
  206. }
  207. /**
  208. * email_send is used by NETWORK_EMAIL and NETWORK_EMAIL2 code
  209. * (not to notify the user, but to send items to email contacts)
  210. *
  211. * @todo This could be changed to use the Emailer class
  212. */
  213. function email_send($addr, $subject, $headers, $item) {
  214. //$headers .= 'MIME-Version: 1.0' . "\n";
  215. //$headers .= 'Content-Type: text/html; charset=UTF-8' . "\n";
  216. //$headers .= 'Content-Type: text/plain; charset=UTF-8' . "\n";
  217. //$headers .= 'Content-Transfer-Encoding: 8bit' . "\n\n";
  218. $part = uniqid("", true);
  219. $html = prepare_body($item);
  220. $headers .= "Mime-Version: 1.0\n";
  221. $headers .= 'Content-Type: multipart/alternative; boundary="=_'.$part.'"'."\n\n";
  222. $body = "\n--=_".$part."\n";
  223. $body .= "Content-Transfer-Encoding: 8bit\n";
  224. $body .= "Content-Type: text/plain; charset=utf-8; format=flowed\n\n";
  225. $body .= html2plain($html)."\n";
  226. $body .= "--=_".$part."\n";
  227. $body .= "Content-Transfer-Encoding: 8bit\n";
  228. $body .= "Content-Type: text/html; charset=utf-8\n\n";
  229. $body .= '<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">'.$html."</body></html>\n";
  230. $body .= "--=_".$part."--";
  231. //$message = '<html><body>' . $html . '</body></html>';
  232. //$message = html2plain($html);
  233. logger('notifier: email delivery to ' . $addr);
  234. mail($addr, $subject, $body, $headers);
  235. }
  236. function iri2msgid($iri) {
  237. if (!strpos($iri, "@"))
  238. $msgid = preg_replace("/urn:(\S+):(\S+)\.(\S+):(\d+):(\S+)/i", "urn!$1!$4!$5@$2.$3", $iri);
  239. else
  240. $msgid = $iri;
  241. return($msgid);
  242. }
  243. function msgid2iri($msgid) {
  244. if (strpos($msgid, "@"))
  245. $iri = preg_replace("/urn!(\S+)!(\d+)!(\S+)@(\S+)\.(\S+)/i", "urn:$1:$4.$5:$2:$3", $msgid);
  246. else
  247. $iri = $msgid;
  248. return($iri);
  249. }