smtp.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. <?php
  2. /**
  3. * smtp.php
  4. *
  5. * Copyright (c) 1999-2001 The SquirrelMail Development Team
  6. * Licensed under the GNU GPL. For full terms see the file COPYING.
  7. *
  8. * This contains all the functions needed to send messages through
  9. * an smtp server or sendmail.
  10. *
  11. * $Id$
  12. */
  13. /*****************************************************************/
  14. /*** THIS FILE NEEDS TO HAVE ITS FORMATTING FIXED!!! ***/
  15. /*** PLEASE DO SO AND REMOVE THIS COMMENT SECTION. ***/
  16. /*** + Base level indent should begin at left margin, as ***/
  17. /*** the require_once and global lines below. ***/
  18. /*** + All identation should consist of four space blocks ***/
  19. /*** + Tab characters are evil. ***/
  20. /*** + all comments should use "slash-star ... star-slash" ***/
  21. /*** style -- no pound characters, no slash-slash style ***/
  22. /*** + FLOW CONTROL STATEMENTS (if, while, etc) SHOULD ***/
  23. /*** ALWAYS USE { AND } CHARACTERS!!! ***/
  24. /*** + Please use ' instead of ", when possible. Note " ***/
  25. /*** should always be used in _( ) function calls. ***/
  26. /*** Thank you for your help making the SM code more readable. ***/
  27. /*****************************************************************/
  28. require_once('../functions/addressbook.php');
  29. require_once('../functions/plugin.php');
  30. require_once('../functions/prefs.php');
  31. global $username, $popuser, $domain;
  32. // This should most probably go to some initialization...
  33. if (ereg("^([^@%/]+)[@%/](.+)$", $username, $usernamedata)) {
  34. $popuser = $usernamedata[1];
  35. $domain = $usernamedata[2];
  36. unset($usernamedata);
  37. } else {
  38. $popuser = $username;
  39. }
  40. // We need domain for smtp
  41. if (!$domain)
  42. $domain = getenv('HOSTNAME');
  43. // Returns true only if this message is multipart
  44. function isMultipart () {
  45. global $attachments;
  46. if (count($attachments)>0)
  47. return true;
  48. else
  49. return false;
  50. }
  51. // looks up aliases in the addressbook and expands them to
  52. // the full address.
  53. // Adds @$domain if it wasn't in the address book and if it
  54. // doesn't have an @ symbol in it
  55. function expandAddrs ($array) {
  56. global $domain;
  57. // don't show errors -- kinda critical that we don't see
  58. // them here since the redirect won't work if we do show them
  59. $abook = addressbook_init(false);
  60. for ($i=0; $i < count($array); $i++) {
  61. $result = $abook->lookup($array[$i]);
  62. $ret = "";
  63. if (isset($result['email'])) {
  64. if (isset($result['name'])) {
  65. $ret = '"'.$result['name'].'" ';
  66. }
  67. $ret .= '<'.$result['email'].'>';
  68. $array[$i] = $ret;
  69. }
  70. else
  71. {
  72. if (strpos($array[$i], '@') === false)
  73. $array[$i] .= '@' . $domain;
  74. $array[$i] = '<' . $array[$i] . '>';
  75. }
  76. }
  77. return $array;
  78. }
  79. // looks up aliases in the addressbook and expands them to
  80. // the RFC 821 valid RCPT address. ie <user@example.com>
  81. // Adds @$domain if it wasn't in the address book and if it
  82. // doesn't have an @ symbol in it
  83. function expandRcptAddrs ($array) {
  84. global $domain;
  85. // don't show errors -- kinda critical that we don't see
  86. // them here since the redirect won't work if we do show them
  87. $abook = addressbook_init(false);
  88. for ($i=0; $i < count($array); $i++) {
  89. $result = $abook->lookup($array[$i]);
  90. $ret = "";
  91. if (isset($result['email'])) {
  92. $ret = '<'.$result['email'].'>';
  93. $array[$i] = $ret;
  94. }
  95. else
  96. {
  97. if (strpos($array[$i], '@') === false)
  98. $array[$i] .= '@' . $domain;
  99. $array[$i] = '<' . $array[$i] . '>';
  100. }
  101. }
  102. return $array;
  103. }
  104. // Attach the files that are due to be attached
  105. function attachFiles ($fp) {
  106. global $attachments, $attachment_dir, $username;
  107. $length = 0;
  108. $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
  109. if (isMultipart()) {
  110. foreach ($attachments as $info)
  111. {
  112. if (isset($info['type']))
  113. $filetype = $info['type'];
  114. else
  115. $filetype = 'application/octet-stream';
  116. $header = '--'.mimeBoundary()."\r\n";
  117. $header .= "Content-Type: $filetype; name=\"" .
  118. $info['remotefilename'] . "\"\r\n";
  119. $header .= "Content-Disposition: attachment; filename=\"" .
  120. $info['remotefilename'] . "\"\r\n";
  121. // Use 'rb' for NT systems -- read binary
  122. // Unix doesn't care -- everything's binary! :-)
  123. $filename = $hashed_attachment_dir . '/' . $info['localfilename'];
  124. $file = fopen ($filename, 'rb');
  125. if (substr($filetype, 0, 5) == 'text/' ||
  126. $filetype == 'message/rfc822') {
  127. $header .= "\r\n";
  128. fputs ($fp, $header);
  129. $length += strlen($header);
  130. while ($tmp = fgets($file, 4096)) {
  131. $tmp = str_replace("\r\n", "\n", $tmp);
  132. $tmp = str_replace("\r", "\n", $tmp);
  133. $tmp = str_replace("\n", "\r\n", $tmp);
  134. if (feof($fp) && substr($tmp, -2) != "\r\n")
  135. $tmp .= "\r\n";
  136. fputs($fp, $tmp);
  137. $length += strlen($tmp);
  138. }
  139. } else {
  140. $header .= "Content-Transfer-Encoding: base64\r\n\r\n";
  141. fputs ($fp, $header);
  142. $length += strlen($header);
  143. while ($tmp = fread($file, 570)) {
  144. $encoded = chunk_split(base64_encode($tmp));
  145. $length += strlen($encoded);
  146. fputs ($fp, $encoded);
  147. }
  148. }
  149. fclose ($file);
  150. }
  151. }
  152. return $length;
  153. }
  154. // Delete files that are uploaded for attaching
  155. function deleteAttachments() {
  156. global $attachments, $attachment_dir;
  157. $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
  158. if (isMultipart()) {
  159. reset($attachments);
  160. while (list($localname, $remotename) = each($attachments)) {
  161. if (!ereg ("\\/", $localname)) {
  162. $filename = $hashed_attachment_dir . '/' . $localname;
  163. unlink ($filename);
  164. unlink ("$filename.info");
  165. }
  166. }
  167. }
  168. }
  169. // Return a nice MIME-boundary
  170. function mimeBoundary () {
  171. static $mimeBoundaryString;
  172. if ($mimeBoundaryString == "") {
  173. $mimeBoundaryString = "----=_" .
  174. GenerateRandomString(60, '\'()+,-./:=?_', 7);
  175. }
  176. return $mimeBoundaryString;
  177. }
  178. /* Time offset for correct timezone */
  179. function timezone () {
  180. global $invert_time;
  181. $diff_second = date('Z');
  182. if ($invert_time)
  183. $diff_second = - $diff_second;
  184. if ($diff_second > 0)
  185. $sign = '+';
  186. else
  187. $sign = '-';
  188. $diff_second = abs($diff_second);
  189. $diff_hour = floor ($diff_second / 3600);
  190. $diff_minute = floor (($diff_second-3600*$diff_hour) / 60);
  191. $zonename = '('.strftime('%Z').')';
  192. $result = sprintf ("%s%02d%02d %s", $sign, $diff_hour, $diff_minute, $zonename);
  193. return ($result);
  194. }
  195. /* Print all the needed RFC822 headers */
  196. function write822Header ($fp, $t, $c, $b, $subject, $more_headers) {
  197. global $REMOTE_ADDR, $SERVER_NAME, $REMOTE_PORT;
  198. global $data_dir, $username, $popuser, $domain, $version, $useSendmail;
  199. global $default_charset, $HTTP_VIA, $HTTP_X_FORWARDED_FOR;
  200. global $REMOTE_HOST, $identity;
  201. // Storing the header to make sure the header is the same
  202. // everytime the header is printed.
  203. static $header, $headerlength;
  204. if ($header == '') {
  205. $to = expandAddrs(parseAddrs($t));
  206. $cc = expandAddrs(parseAddrs($c));
  207. $bcc = expandAddrs(parseAddrs($b));
  208. if (isset($identity) && $identity != 'default')
  209. {
  210. $reply_to = getPref($data_dir, $username, 'reply_to' . $identity);
  211. $from = getPref($data_dir, $username, 'full_name' . $identity);
  212. $from_addr = getPref($data_dir, $username, 'email_address' . $identity);
  213. }
  214. else
  215. {
  216. $reply_to = getPref($data_dir, $username, 'reply_to');
  217. $from = getPref($data_dir, $username, 'full_name');
  218. $from_addr = getPref($data_dir, $username, 'email_address');
  219. }
  220. if ($from_addr == '')
  221. $from_addr = $popuser.'@'.$domain;
  222. $to_list = getLineOfAddrs($to);
  223. $cc_list = getLineOfAddrs($cc);
  224. $bcc_list = getLineOfAddrs($bcc);
  225. /* Encoding 8-bit characters and making from line */
  226. $subject = encodeHeader($subject);
  227. if ($from == '')
  228. $from = "<$from_addr>";
  229. else
  230. $from = '"' . encodeHeader($from) . "\" <$from_addr>";
  231. /* This creates an RFC 822 date */
  232. $date = date("D, j M Y H:i:s ", mktime()) . timezone();
  233. /* Create a message-id */
  234. $message_id = '<' . $REMOTE_PORT . '.' . $REMOTE_ADDR . '.';
  235. $message_id .= time() . '.squirrel@' . $SERVER_NAME .'>';
  236. /* Make an RFC822 Received: line */
  237. if (isset($REMOTE_HOST))
  238. $received_from = "$REMOTE_HOST ([$REMOTE_ADDR])";
  239. else
  240. $received_from = $REMOTE_ADDR;
  241. if (isset($HTTP_VIA) || isset ($HTTP_X_FORWARDED_FOR)) {
  242. if ($HTTP_X_FORWARDED_FOR == '')
  243. $HTTP_X_FORWARDED_FOR = 'unknown';
  244. $received_from .= " (proxying for $HTTP_X_FORWARDED_FOR)";
  245. }
  246. $header = "Received: from $received_from\r\n";
  247. $header .= " (SquirrelMail authenticated user $username)\r\n";
  248. $header .= " by $SERVER_NAME with HTTP;\r\n";
  249. $header .= " $date\r\n";
  250. /* Insert the rest of the header fields */
  251. $header .= "Message-ID: $message_id\r\n";
  252. $header .= "Date: $date\r\n";
  253. $header .= "Subject: $subject\r\n";
  254. $header .= "From: $from\r\n";
  255. $header .= "To: $to_list\r\n"; // Who it's TO
  256. /* Insert headers from the $more_headers array */
  257. if(is_array($more_headers)) {
  258. reset($more_headers);
  259. while(list($h_name, $h_val) = each($more_headers)) {
  260. $header .= sprintf("%s: %s\r\n", $h_name, $h_val);
  261. }
  262. }
  263. if ($cc_list) {
  264. $header .= "Cc: $cc_list\r\n"; // Who the CCs are
  265. }
  266. if ($reply_to != '')
  267. $header .= "Reply-To: $reply_to\r\n";
  268. if ($useSendmail) {
  269. if ($bcc_list) {
  270. // BCCs is removed from header by sendmail
  271. $header .= "Bcc: $bcc_list\r\n";
  272. }
  273. }
  274. $header .= "X-Mailer: SquirrelMail (version $version)\r\n"; // Identify SquirrelMail
  275. // Do the MIME-stuff
  276. $header .= "MIME-Version: 1.0\r\n";
  277. if (isMultipart()) {
  278. $header .= 'Content-Type: multipart/mixed; boundary="';
  279. $header .= mimeBoundary();
  280. $header .= "\"\r\n";
  281. } else {
  282. if ($default_charset != '')
  283. $header .= "Content-Type: text/plain; charset=$default_charset\r\n";
  284. else
  285. $header .= "Content-Type: text/plain;\r\n";
  286. $header .= "Content-Transfer-Encoding: 8bit\r\n";
  287. }
  288. $header .= "\r\n"; // One blank line to separate header and body
  289. $headerlength = strlen($header);
  290. }
  291. // Write the header
  292. fputs ($fp, $header);
  293. return $headerlength;
  294. }
  295. // Send the body
  296. function writeBody ($fp, $passedBody) {
  297. global $default_charset;
  298. $attachmentlength = 0;
  299. if (isMultipart()) {
  300. $body = '--'.mimeBoundary()."\r\n";
  301. if ($default_charset != "")
  302. $body .= "Content-Type: text/plain; charset=$default_charset\r\n";
  303. else
  304. $body .= "Content-Type: text/plain\r\n";
  305. $body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
  306. $body .= $passedBody . "\r\n\r\n";
  307. fputs ($fp, $body);
  308. $attachmentlength = attachFiles($fp);
  309. if (!isset($postbody)) $postbody = "";
  310. $postbody .= "\r\n--".mimeBoundary()."--\r\n\r\n";
  311. fputs ($fp, $postbody);
  312. } else {
  313. $body = $passedBody . "\r\n";
  314. fputs ($fp, $body);
  315. $postbody = "\r\n";
  316. fputs ($fp, $postbody);
  317. }
  318. return (strlen($body) + strlen($postbody) + $attachmentlength);
  319. }
  320. // Send mail using the sendmail command
  321. function sendSendmail($t, $c, $b, $subject, $body, $more_headers) {
  322. global $sendmail_path, $popuser, $username, $domain;
  323. // Build envelope sender address. Make sure it doesn't contain
  324. // spaces or other "weird" chars that would allow a user to
  325. // exploit the shell/pipe it is used in.
  326. $envelopefrom = "$popuser@$domain";
  327. $envelopefrom = ereg_replace("[[:blank:]]",'', $envelopefrom);
  328. $envelopefrom = ereg_replace("[[:space:]]",'', $envelopefrom);
  329. $envelopefrom = ereg_replace("[[:cntrl:]]",'', $envelopefrom);
  330. // open pipe to sendmail or qmail-inject (qmail-inject doesn't accept -t param)
  331. if (strstr($sendmail_path, "qmail-inject")) {
  332. $fp = popen (escapeshellcmd("$sendmail_path -f$envelopefrom"), "w");
  333. } else {
  334. $fp = popen (escapeshellcmd("$sendmail_path -t -f$envelopefrom"), "w");
  335. }
  336. $headerlength = write822Header ($fp, $t, $c, $b, $subject, $more_headers);
  337. $bodylength = writeBody($fp, $body);
  338. pclose($fp);
  339. return ($headerlength + $bodylength);
  340. }
  341. function smtpReadData($smtpConnection) {
  342. $read = fgets($smtpConnection, 1024);
  343. $counter = 0;
  344. while ($read) {
  345. echo $read . '<BR>';
  346. $data[$counter] = $read;
  347. $read = fgets($smtpConnection, 1024);
  348. $counter++;
  349. }
  350. }
  351. function sendSMTP($t, $c, $b, $subject, $body, $more_headers) {
  352. global $username, $popuser, $domain, $version, $smtpServerAddress,
  353. $smtpPort, $data_dir, $color, $use_authenticated_smtp, $identity,
  354. $key, $onetimepad;
  355. $to = expandRcptAddrs(parseAddrs($t));
  356. $cc = expandRcptAddrs(parseAddrs($c));
  357. $bcc = expandRcptAddrs(parseAddrs($b));
  358. if (isset($identity) && $identity != 'default')
  359. $from_addr = getPref($data_dir, $username, 'email_address' . $identity);
  360. else
  361. $from_addr = getPref($data_dir, $username, 'email_address');
  362. if (!$from_addr)
  363. $from_addr = "$popuser@$domain";
  364. $smtpConnection = fsockopen($smtpServerAddress, $smtpPort, $errorNumber, $errorString);
  365. if (!$smtpConnection) {
  366. echo 'Error connecting to SMTP Server.<br>';
  367. echo "$errorNumber : $errorString<br>";
  368. exit;
  369. }
  370. $tmp = fgets($smtpConnection, 1024);
  371. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  372. $to_list = getLineOfAddrs($to);
  373. $cc_list = getLineOfAddrs($cc);
  374. /** Lets introduce ourselves */
  375. if (! isset ($use_authenticated_smtp) || $use_authenticated_smtp == false) {
  376. fputs($smtpConnection, "HELO $domain\r\n");
  377. $tmp = fgets($smtpConnection, 1024);
  378. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  379. } else {
  380. fputs($smtpConnection, "EHLO $domain\r\n");
  381. $tmp = fgets($smtpConnection, 1024);
  382. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  383. fputs($smtpConnection, "AUTH LOGIN\r\n");
  384. $tmp = fgets($smtpConnection, 1024);
  385. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  386. fputs($smtpConnection, base64_encode ($username) . "\r\n");
  387. $tmp = fgets($smtpConnection, 1024);
  388. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  389. fputs($smtpConnection, base64_encode (OneTimePadDecrypt($key, $onetimepad)) . "\r\n");
  390. $tmp = fgets($smtpConnection, 1024);
  391. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  392. }
  393. /** Ok, who is sending the message? */
  394. fputs($smtpConnection, "MAIL FROM: <$from_addr>\r\n");
  395. $tmp = fgets($smtpConnection, 1024);
  396. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  397. /** send who the recipients are */
  398. for ($i = 0; $i < count($to); $i++) {
  399. fputs($smtpConnection, "RCPT TO: $to[$i]\r\n");
  400. $tmp = fgets($smtpConnection, 1024);
  401. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  402. }
  403. for ($i = 0; $i < count($cc); $i++) {
  404. fputs($smtpConnection, "RCPT TO: $cc[$i]\r\n");
  405. $tmp = fgets($smtpConnection, 1024);
  406. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  407. }
  408. for ($i = 0; $i < count($bcc); $i++) {
  409. fputs($smtpConnection, "RCPT TO: $bcc[$i]\r\n");
  410. $tmp = fgets($smtpConnection, 1024);
  411. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  412. }
  413. /** Lets start sending the actual message */
  414. fputs($smtpConnection, "DATA\r\n");
  415. $tmp = fgets($smtpConnection, 1024);
  416. if (errorCheck($tmp, $smtpConnection)!=5) return(0);
  417. // Send the message
  418. $headerlength = write822Header ($smtpConnection, $t, $c, $b, $subject, $more_headers);
  419. $bodylength = writeBody($smtpConnection, $body);
  420. fputs($smtpConnection, ".\r\n"); // end the DATA part
  421. $tmp = fgets($smtpConnection, 1024);
  422. $num = errorCheck($tmp, $smtpConnection, true);
  423. if ($num != 250) {
  424. $tmp = nl2br(htmlspecialchars($tmp));
  425. displayPageHeader($color, 'None');
  426. include_once('../functions/display_messages.php');
  427. $msg = "Message not sent!<br>\nReason given: $tmp";
  428. plain_error_message($msg, $color);
  429. return(0);
  430. }
  431. fputs($smtpConnection, "QUIT\r\n"); // log off
  432. fclose($smtpConnection);
  433. return ($headerlength + $bodylength);
  434. }
  435. function errorCheck($line, $smtpConnection, $verbose = false) {
  436. global $color;
  437. // Read new lines on a multiline response
  438. $lines = $line;
  439. while(ereg("^[0-9]+-", $line)) {
  440. $line = fgets($smtpConnection, 1024);
  441. $lines .= $line;
  442. }
  443. // Status: 0 = fatal
  444. // 5 = ok
  445. $err_num = substr($line, 0, strpos($line, " "));
  446. switch ($err_num) {
  447. case 500: $message = 'Syntax error; command not recognized';
  448. $status = 0;
  449. break;
  450. case 501: $message = 'Syntax error in parameters or arguments';
  451. $status = 0;
  452. break;
  453. case 502: $message = 'Command not implemented';
  454. $status = 0;
  455. break;
  456. case 503: $message = 'Bad sequence of commands';
  457. $status = 0;
  458. break;
  459. case 504: $message = 'Command parameter not implemented';
  460. $status = 0;
  461. break;
  462. case 211: $message = 'System status, or system help reply';
  463. $status = 5;
  464. break;
  465. case 214: $message = 'Help message';
  466. $status = 5;
  467. break;
  468. case 220: $message = 'Service ready';
  469. $status = 5;
  470. break;
  471. case 221: $message = 'Service closing transmission channel';
  472. $status = 5;
  473. break;
  474. case 421: $message = 'Service not available, closing chanel';
  475. $status = 0;
  476. break;
  477. case 235: return(5); break;
  478. case 250: $message = 'Requested mail action okay, completed';
  479. $status = 5;
  480. break;
  481. case 251: $message = 'User not local; will forward';
  482. $status = 5;
  483. break;
  484. case 334: return(5); break;
  485. case 450: $message = 'Requested mail action not taken: mailbox unavailable';
  486. $status = 0;
  487. break;
  488. case 550: $message = 'Requested action not taken: mailbox unavailable';
  489. $status = 0;
  490. break;
  491. case 451: $message = 'Requested action aborted: error in processing';
  492. $status = 0;
  493. break;
  494. case 551: $message = 'User not local; please try forwarding';
  495. $status = 0;
  496. break;
  497. case 452: $message = 'Requested action not taken: insufficient system storage';
  498. $status = 0;
  499. break;
  500. case 552: $message = 'Requested mail action aborted: exceeding storage allocation';
  501. $status = 0;
  502. break;
  503. case 553: $message = 'Requested action not taken: mailbox name not allowed';
  504. $status = 0;
  505. break;
  506. case 354: $message = 'Start mail input; end with .';
  507. $status = 5;
  508. break;
  509. case 554: $message = 'Transaction failed';
  510. $status = 0;
  511. break;
  512. default: $message = 'Unknown response: '. nl2br(htmlspecialchars($lines));
  513. $status = 0;
  514. $error_num = '001';
  515. break;
  516. }
  517. if ($status == 0) {
  518. include_once('../functions/page_header.php');
  519. displayPageHeader($color, 'None');
  520. include_once('../functions/display_messages.php');
  521. $lines = nl2br(htmlspecialchars($lines));
  522. $msg = $message . "<br>\nServer replied: $lines";
  523. plain_error_message($msg, $color);
  524. }
  525. if (! $verbose) return $status;
  526. return $err_num;
  527. }
  528. function sendMessage($t, $c, $b, $subject, $body, $reply_id, $prio = 3) {
  529. global $useSendmail, $msg_id, $is_reply, $mailbox, $onetimepad;
  530. global $data_dir, $username, $domain, $key, $version, $sent_folder, $imapServerAddress, $imapPort;
  531. global $default_use_priority;
  532. global $more_headers;
  533. $more_headers = Array();
  534. do_hook("smtp_send");
  535. $imap_stream = sqimap_login($username, $key, $imapServerAddress, $imapPort, 1);
  536. if (isset($reply_id) && $reply_id) {
  537. sqimap_mailbox_select ($imap_stream, $mailbox);
  538. sqimap_messages_flag ($imap_stream, $reply_id, $reply_id, 'Answered');
  539. // Insert In-Reply-To and References headers if the
  540. // message-id of the message we reply to is set (longer than "<>")
  541. // The References header should really be the old Referenced header
  542. // with the message ID appended, but it can be only the message ID too.
  543. $hdr = sqimap_get_small_header ($imap_stream, $reply_id, false);
  544. if(strlen($hdr->message_id) > 2) {
  545. $more_headers['In-Reply-To'] = $hdr->message_id;
  546. $more_headers['References'] = $hdr->message_id;
  547. }
  548. }
  549. if ($default_use_priority) {
  550. $more_headers = array_merge($more_headers, createPriorityHeaders($prio));
  551. }
  552. // In order to remove the problem of users not able to create
  553. // messages with "." on a blank line, RFC821 has made provision
  554. // in section 4.5.2 (Transparency).
  555. $body = ereg_replace("\n\\.", "\n..", $body);
  556. $body = ereg_replace("^\\.", "..", $body);
  557. // this is to catch all plain \n instances and
  558. // replace them with \r\n. All newlines were converted
  559. // into just \n inside the compose.php file.
  560. $body = ereg_replace("\n", "\r\n", $body);
  561. if ($useSendmail) {
  562. $length = sendSendmail($t, $c, $b, $subject, $body, $more_headers);
  563. } else {
  564. $length = sendSMTP($t, $c, $b, $subject, $body, $more_headers);
  565. }
  566. if (sqimap_mailbox_exists ($imap_stream, $sent_folder)) {
  567. sqimap_append ($imap_stream, $sent_folder, $length);
  568. write822Header ($imap_stream, $t, $c, $b, $subject, $more_headers);
  569. writeBody ($imap_stream, $body);
  570. sqimap_append_done ($imap_stream);
  571. }
  572. sqimap_logout($imap_stream);
  573. // Delete the files uploaded for attaching (if any).
  574. // only if $length != 0 (if there was no error)
  575. if ($length)
  576. ClearAttachments();
  577. return $length;
  578. }
  579. function createPriorityHeaders($prio) {
  580. $prio_headers = Array();
  581. $prio_headers["X-Priority"] = $prio;
  582. switch($prio) {
  583. case 1: $prio_headers["Importance"] = "High";
  584. $prio_headers["X-MSMail-Priority"] = "High";
  585. break;
  586. case 3: $prio_headers["Importance"] = "Normal";
  587. $prio_headers["X-MSMail-Priority"] = "Normal";
  588. break;
  589. case 5:
  590. $prio_headers["Importance"] = "Low";
  591. $prio_headers["X-MSMail-Priority"] = "Low";
  592. break;
  593. }
  594. return $prio_headers;
  595. }
  596. ?>