Happy New Year
[squirrelmail.git] / src / compose.php
CommitLineData
59177427 1<?php
35586184 2/**
3 * compose.php
4 *
35586184 5 * This code sends a mail.
6 *
7 * There are 4 modes of operation:
8 * - Start new mail
9 * - Add an attachment
10 * - Send mail
11 * - Save As Draft
12 *
8ed19238 13 * @copyright 1999-2019 The SquirrelMail Project Team
4b4abf93 14 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
30967a1e 15 * @version $Id$
8f6f9ba5 16 * @package squirrelmail
35586184 17 */
f7fb20fe 18
ebd2391c 19/** This is the compose page */
20define('PAGE_NAME', 'compose');
21
30967a1e 22/**
202bcbcc 23 * Include the SquirrelMail initialization file.
30967a1e 24 */
202bcbcc 25require('../include/init.php');
86725763 26
c90271cb 27/* If email_address not set and admin wants us to ask user for it,
28 * redirect to options page. */
29if ( $ask_user_info && getPref($data_dir, $username,'email_address') == "" ) {
30 header("Location: " . get_location() . "/options.php?optpage=personal");
31 exit;
32}
33
86725763 34/* SquirrelMail required files. */
202bcbcc 35require_once(SM_PATH . 'functions/imap_general.php');
36require_once(SM_PATH . 'functions/imap_messages.php');
86725763 37require_once(SM_PATH . 'functions/date.php');
38require_once(SM_PATH . 'functions/mime.php');
628bce99 39require_once(SM_PATH . 'functions/compose.php');
86725763 40require_once(SM_PATH . 'class/deliver/Deliver.class.php');
24192f77 41require_once(SM_PATH . 'functions/addressbook.php');
df96b37a 42require_once(SM_PATH . 'functions/forms.php');
a2b193bc 43require_once(SM_PATH . 'functions/identity.php');
a9805897 44global $imap_stream_options; // in case not defined in config
91f2085b 45
0b97a708 46/* --------------------- Get globals ------------------------------------- */
0b97a708 47
953fa718 48/** SESSION VARS */
953fa718 49sqgetGlobalVar('delimiter', $delimiter, SQ_SESSION);
50
f8eb968d 51sqgetGlobalVar('delayed_errors', $delayed_errors, SQ_SESSION);
953fa718 52sqgetGlobalVar('composesession', $composesession, SQ_SESSION);
53sqgetGlobalVar('compose_messages', $compose_messages, SQ_SESSION);
f8eb968d 54
55// compose_messages only useful in SESSION when a forward-as-attachment
56// has been preconstructed for us and passed in via that mechanism; once
57// we have it, we can clear it from the SESSION
7b2092f1 58// -- No, this is useful in other scenarios, too -- removing:
59// sqsession_unregister('compose_messages');
762853f4 60
61// Turn on delayed error handling in case we wind up redirecting below
62$oErrorHandler->setDelayedErrors(true);
953fa718 63
64/** SESSION/POST/GET VARS */
61bd57f5 65sqgetGlobalVar('send_button_count', $send_button_count, SQ_POST, 1, SQ_TYPE_INT);
66for ($i = 1; $i <= $send_button_count; $i++)
67 if (sqgetGlobalVar('send' . $i, $send, SQ_POST)) break;
567dc524 68// Send can only be achieved by setting $_POST var. If Send = true then
69// retrieve other form fields from $_POST
70if (isset($send) && $send) {
71 $SQ_GLOBAL = SQ_POST;
72} else {
73 $SQ_GLOBAL = SQ_FORM;
74}
75sqgetGlobalVar('session',$session, $SQ_GLOBAL);
76sqgetGlobalVar('mailbox',$mailbox, $SQ_GLOBAL);
79cecc00 77sqgetGlobalVar('identity',$orig_identity, $SQ_GLOBAL);
567dc524 78if(!sqgetGlobalVar('identity',$identity, $SQ_GLOBAL)) {
1e2a6ff6 79 $identity=0;
80}
567dc524 81sqgetGlobalVar('send_to',$send_to, $SQ_GLOBAL);
82sqgetGlobalVar('send_to_cc',$send_to_cc, $SQ_GLOBAL);
83sqgetGlobalVar('send_to_bcc',$send_to_bcc, $SQ_GLOBAL);
84sqgetGlobalVar('subject',$subject, $SQ_GLOBAL);
85sqgetGlobalVar('body',$body, $SQ_GLOBAL);
86sqgetGlobalVar('mailprio',$mailprio, $SQ_GLOBAL);
87sqgetGlobalVar('request_mdn',$request_mdn, $SQ_GLOBAL);
88sqgetGlobalVar('request_dr',$request_dr, $SQ_GLOBAL);
89sqgetGlobalVar('html_addr_search',$html_addr_search, $SQ_GLOBAL);
90sqgetGlobalVar('mail_sent',$mail_sent, $SQ_GLOBAL);
51bbe8fa 91sqgetGlobalVar('passed_id',$passed_id, $SQ_GLOBAL, NULL, SQ_TYPE_BIGINT);
567dc524 92sqgetGlobalVar('passed_ent_id',$passed_ent_id, $SQ_GLOBAL);
e506b6e5 93sqgetGlobalVar('fwduid',$fwduid, $SQ_GLOBAL, '');
12a0ed01 94
567dc524 95sqgetGlobalVar('attach',$attach, SQ_POST);
96sqgetGlobalVar('draft',$draft, SQ_POST);
97sqgetGlobalVar('draft_id',$draft_id, $SQ_GLOBAL);
98sqgetGlobalVar('ent_num',$ent_num, $SQ_GLOBAL);
99sqgetGlobalVar('saved_draft',$saved_draft, SQ_FORM);
7e2ff844 100
101if ( sqgetGlobalVar('delete_draft',$delete_draft) ) {
102 $delete_draft = (int)$delete_draft;
103}
104
a6d3eff6 105if ( sqgetGlobalVar('startMessage',$startMessage) ) {
106 $startMessage = (int)$startMessage;
107} else {
108 $startMessage = 1;
109}
953fa718 110
8780308f 111
953fa718 112/** POST VARS */
167c6996 113sqgetGlobalVar('sigappend', $sigappend, SQ_POST);
114sqgetGlobalVar('from_htmladdr_search', $from_htmladdr_search, SQ_POST);
115sqgetGlobalVar('addr_search_done', $html_addr_search_done, SQ_POST);
116sqgetGlobalVar('addr_search_cancel', $html_addr_search_cancel, SQ_POST);
117sqgetGlobalVar('send_to_search', $send_to_search, SQ_POST);
118sqgetGlobalVar('do_delete', $do_delete, SQ_POST);
119sqgetGlobalVar('delete', $delete, SQ_POST);
f8eb968d 120sqgetGlobalVar('attachments', $attachments, SQ_POST);
953fa718 121if ( sqgetGlobalVar('return', $temp, SQ_POST) ) {
73ad81bf 122 $html_addr_search_done = 'Use Addresses';
953fa718 123}
124
125/** GET VARS */
8780308f 126if ( sqgetGlobalVar('account', $temp, SQ_GET) ) {
127 $iAccount = (int) $temp;
128} else {
129 $iAccount = 0;
130}
131
0b97a708 132
98a9cc03 133/** get smaction */
134if ( !sqgetGlobalVar('smaction',$action) )
135{
73ad81bf 136 if ( sqgetGlobalVar('smaction_reply',$tmp) ) $action = 'reply';
137 if ( sqgetGlobalVar('smaction_reply_all',$tmp) ) $action = 'reply_all';
138 if ( sqgetGlobalVar('smaction_forward',$tmp) ) $action = 'forward';
139 if ( sqgetGlobalVar('smaction_attache',$tmp) ) $action = 'forward_as_attachment';
140 if ( sqgetGlobalVar('smaction_draft',$tmp) ) $action = 'draft';
141 if ( sqgetGlobalVar('smaction_edit_new',$tmp) ) $action = 'edit_as_new';
98a9cc03 142}
143
199a9ab8 144sqgetGlobalVar('smtoken', $submitted_token, $SQ_GLOBAL, '');
145
7e2ff844 146/**
147 * Here we decode the data passed in from mailto.php.
148 */
149if ( sqgetGlobalVar('mailtodata', $mailtodata, SQ_GET) ) {
150 $trtable = array('to' => 'send_to',
151 'cc' => 'send_to_cc',
152 'bcc' => 'send_to_bcc',
153 'body' => 'body',
154 'subject' => 'subject');
155 $mtdata = unserialize($mailtodata);
1638beb6 156
7e2ff844 157 foreach ($trtable as $f => $t) {
158 if ( !empty($mtdata[$f]) ) {
159 $$t = $mtdata[$f];
160 }
161 }
162 unset($mailtodata,$mtdata, $trtable);
163}
164
39cf816f 165/* Location (For HTTP 1.1 header("Location: ...") redirects) */
3461167c 166$location = get_location();
1e2a6ff6 167/* Identities (fetch only once) */
168$idents = get_identities();
3461167c 169
09044055 170/* --------------------- Specific Functions ------------------------------ */
0b97a708 171
41b94d65 172function replyAllString($header) {
73ad81bf 173 global $include_self_reply_all, $idents;
174 $excl_ar = array();
175 /**
176 * 1) Remove the addresses we'll be sending the message 'to'
177 */
af084f6e 178 if (isset($header->reply_to)) {
179 $excl_ar = $header->getAddr_a('reply_to');
73ad81bf 180 }
181 /**
182 * 2) Remove our identities from the CC list (they still can be in the
183 * TO list) only if $include_self_reply_all is turned off
184 */
185 if (!$include_self_reply_all) {
186 foreach($idents as $id) {
187 $excl_ar[strtolower(trim($id['email_address']))] = '';
188 }
189 }
190
191 /**
192 * 3) get the addresses.
193 */
194 $url_replytoall_ar = $header->getAddr_a(array('to','cc'), $excl_ar);
195
196 /**
197 * 4) generate the string.
198 */
199 $url_replytoallcc = '';
200 foreach( $url_replytoall_ar as $email => $personal) {
201 if ($personal) {
a9b9e5d3 202 // always quote personal name (can't just quote it if
203 // it contains a comma separator, since it might still
204 // be encoded)
205 $url_replytoallcc .= ", \"$personal\" <$email>";
73ad81bf 206 } else {
207 $url_replytoallcc .= ', '. $email;
1e2a6ff6 208 }
73ad81bf 209 }
210 $url_replytoallcc = substr($url_replytoallcc,2);
211
212 return $url_replytoallcc;
09044055 213}
214
50706f77 215/**
216 * creates top line in reply citations
217 *
218 * Line style depends on user preferences.
219 * $orig_date argument is available only from 1.4.3 and 1.5.1 version.
220 * @param object $orig_from From: header object.
221 * @param integer $orig_date email's timestamp
222 * @return string reply citation
223 */
b0323712 224function getReplyCitation($orig_from, $orig_date) {
12a0ed01 225 global $reply_citation_style, $reply_citation_start, $reply_citation_end;
50706f77 226
05f7db7a 227 if (!is_object($orig_from)) {
d1205176 228 $sOrig_from = '';
05f7db7a 229 } else {
d1205176 230 $sOrig_from = decodeHeader($orig_from->getAddress(false),false,false,true);
05f7db7a 231 }
91c27aee 232
12a0ed01 233 /* First, return an empty string when no citation style selected. */
234 if (($reply_citation_style == '') || ($reply_citation_style == 'none')) {
235 return '';
236 }
237
238 /* Make sure our final value isn't an empty string. */
d1205176 239 if ($sOrig_from == '') {
12a0ed01 240 return '';
241 }
242
243 /* Otherwise, try to select the desired citation style. */
244 switch ($reply_citation_style) {
50706f77 245 case 'author_said':
b986936a 246 // i18n: %s is for author's name
d1205176 247 $full_reply_citation = sprintf(_("%s wrote:"),$sOrig_from);
50706f77 248 break;
249 case 'quote_who':
7b2092f1 250 // TODO: the words "quote" and "who" are translated in 1.4.x so why not here? This isn't a real HTML tag...
a42c236f 251 $start = '<quote who="';
50706f77 252 $end = '">';
d1205176 253 $full_reply_citation = $start . $sOrig_from . $end;
50706f77 254 break;
255 case 'date_time_author':
b986936a 256 // i18n:
257 // The first %s is for date string, the second %s is for author's name.
258 // The date uses formating from "D, F j, Y g:i a" and "D, F j, Y H:i"
259 // translations.
260 // Example string:
261 // "On Sat, December 24, 2004 23:59, Santa wrote:"
262 // If you have to put author's name in front of date string, check comments about
263 // argument swapping at http://php.net/sprintf
d1205176 264 $full_reply_citation = sprintf(_("On %s, %s wrote:"), getLongDateString($orig_date), $sOrig_from);
50706f77 265 break;
266 case 'user-defined':
267 $start = $reply_citation_start .
268 ($reply_citation_start == '' ? '' : ' ');
269 $end = $reply_citation_end;
d1205176 270 $full_reply_citation = $start . $sOrig_from . $end;
50706f77 271 break;
272 default:
273 return '';
274 }
275
276 /* Add line feed and return the citation string. */
277 return ($full_reply_citation . "\n");
12a0ed01 278}
279
50706f77 280/**
281 * Creates header fields in forwarded email body
282 *
91c27aee 283 * $default_charset global must be set correctly before you call this function.
50706f77 284 * @param object $orig_header
91c27aee 285 * @return $string
50706f77 286 */
41b94d65 287function getforwardHeader($orig_header) {
50706f77 288 global $editor_size, $default_charset;
289
290 // using own strlen function in order to detect correct string length
291 $display = array( _("Subject") => sq_strlen(_("Subject"),$default_charset),
292 _("From") => sq_strlen(_("From"),$default_charset),
293 _("Date") => sq_strlen(_("Date"),$default_charset),
294 _("To") => sq_strlen(_("To"),$default_charset),
295 _("Cc") => sq_strlen(_("Cc"),$default_charset) );
73ad81bf 296 $maxsize = max($display);
297 $indent = str_pad('',$maxsize+2);
298 foreach($display as $key => $val) {
299 $display[$key] = $key .': '. str_pad('', $maxsize - $val);
300 }
301 $from = decodeHeader($orig_header->getAddr_s('from',"\n$indent"),false,false,true);
302 $from = str_replace('&nbsp;',' ',$from);
303 $to = decodeHeader($orig_header->getAddr_s('to',"\n$indent"),false,false,true);
304 $to = str_replace('&nbsp;',' ',$to);
305 $subject = decodeHeader($orig_header->subject,false,false,true);
306 $subject = str_replace('&nbsp;',' ',$subject);
50706f77 307
308 // using own str_pad function in order to create correct string pad
309 $bodyTop = sq_str_pad(' '._("Original Message").' ',$editor_size -2,'-',STR_PAD_BOTH,$default_charset) .
73ad81bf 310 "\n". $display[_("Subject")] . $subject . "\n" .
311 $display[_("From")] . $from . "\n" .
3aaa3214 312 $display[_("Date")] . getLongDateString( $orig_header->date, $orig_header->date_unparsed ). "\n" .
73ad81bf 313 $display[_("To")] . $to . "\n";
314 if ($orig_header->cc != array() && $orig_header->cc !='') {
315 $cc = decodeHeader($orig_header->getAddr_s('cc',"\n$indent"),false,false,true);
316 $cc = str_replace('&nbsp;',' ',$cc);
317 $bodyTop .= $display[_("Cc")] .$cc . "\n";
318 }
319 $bodyTop .= str_pad('', $editor_size -2 , '-') .
320 "\n\n";
321 return $bodyTop;
41b94d65 322}
09044055 323/* ----------------------------------------------------------------------- */
324
44560457 325/*
1c044820 326 * If the session is expired during a post this restores the compose session
44560457 327 * vars.
328 */
f8eb968d 329$session_expired = false;
5da08ef7 330if (sqsession_is_registered('session_expired_post')) {
953fa718 331 sqgetGlobalVar('session_expired_post', $session_expired_post, SQ_SESSION);
1c044820 332 /*
40934000 333 * extra check for username so we don't display previous post data from
334 * another user during this session.
335 */
c7ebdfcf 336 if (!empty($session_expired_post['username'])
337 && $session_expired_post['username'] == $username) {
1638beb6 338 // these are the vars that we can set from the expired composed session
f8eb968d 339 $compo_var_list = array ('send_to', 'send_to_cc', 'body',
340 'startMessage', 'passed_body', 'use_signature', 'signature',
341 'subject', 'newmail', 'send_to_bcc', 'passed_id', 'mailbox',
342 'from_htmladdr_search', 'identity', 'draft_id', 'delete_draft',
343 'mailprio', 'edit_as_new', 'attachments', 'composesession',
e506b6e5 344 'request_mdn', 'request_dr', 'fwduid');
c6f28eb1 345
346 foreach ($compo_var_list as $var) {
347 if ( isset($session_expired_post[$var]) && !isset($$var) ) {
774d79cc 348 $$var = $session_expired_post[$var];
61e96f7e 349 }
40934000 350 }
c6f28eb1 351
f8eb968d 352 if (!empty($attachments))
177cb345 353 $attachments = unserialize(urldecode($attachments));
f8eb968d 354
0ec1a14b 355 sqsession_register($composesession,'composesession');
f8eb968d 356
40934000 357 if (isset($send)) {
358 unset($send);
359 }
360 $session_expired = true;
361 }
5da08ef7 362 unset($session_expired_post);
0b97a708 363 sqsession_unregister('session_expired_post');
5da08ef7 364 session_write_close();
40934000 365 if (!isset($mailbox)) {
366 $mailbox = '';
367 }
368 if ($compose_new_win == '1') {
369 compose_Header($color, $mailbox);
370 } else {
91c27aee 371 $sHeaderJs = (isset($sHeaderJs)) ? $sHeaderJs : '';
372 if (strpos($action, 'reply') !== false && $reply_focus) {
ca14ebb7 373 $sOnload = 'checkForm(\''.$replyfocus.'\');';
91c27aee 374 } else {
ca14ebb7 375 $sOnload = 'checkForm();';
91c27aee 376 }
ca14ebb7 377 displayPageHeader($color, $mailbox,$sHeaderJs,$sOnload);
40934000 378 }
379 showInputForm($session, false);
380 exit();
44560457 381}
f8eb968d 382
da95c4b6 383if (!isset($composesession)) {
384 $composesession = 0;
a43e4b90 385 sqsession_register(0,'composesession');
7e2ff844 386} else {
387 $composesession = (int)$composesession;
da95c4b6 388}
389
d7f8e6e6 390if (!isset($session) || (isset($newmessage) && $newmessage)) {
0b97a708 391 sqsession_unregister('composesession');
1c044820 392 $session = "$composesession" +1;
91f2085b 393 $composesession = $session;
a43e4b90 394 sqsession_register($composesession,'composesession');
1c044820 395}
b4e7df34 396if (!empty($compose_messages[$session])) {
397 $composeMessage = $compose_messages[$session];
398} else {
73ad81bf 399 $composeMessage = new Message();
400 $rfc822_header = new Rfc822Header();
401 $composeMessage->rfc822_header = $rfc822_header;
402 $composeMessage->reply_rfc822_header = '';
a43e4b90 403}
a43e4b90 404
f8eb968d 405// re-add attachments that were already in this message
406// FIXME: note that technically this is very bad form -
407// should never directly manipulate an object like this
408if (!empty($attachments)) {
177cb345 409 $attachments = unserialize(urldecode($attachments));
dc242580 410 if (!empty($attachments) && is_array($attachments)) {
411 // sanitize the "att_local_name" since it is user-supplied and used to access the file system
412 // it must be alpha-numeric and 32 characters long (see the use of GenerateRandomString() below)
413 foreach ($attachments as $i => $attachment) {
414 if (empty($attachment->att_local_name) || strlen($attachment->att_local_name) !== 32) {
415 unset($attachments[$i]);
416 continue;
417 }
418 // probably marginal difference between (ctype_alnum + function_exists) and preg_match
419 if (function_exists('ctype_alnum')) {
420 if (!ctype_alnum($attachment->att_local_name))
421 unset($attachments[$i]);
422 }
423 else if (preg_match('/[^0-9a-zA-Z]/', $attachment->att_local_name))
424 unset($attachments[$i]);
425 }
426 if (!empty($attachments))
427 $composeMessage->entities = $attachments;
428 }
f8eb968d 429}
430
876fdb60 431if (empty($mailbox)) {
00793a25 432 $mailbox = 'INBOX';
433}
434
4dfb9db7 435if ($draft) {
199a9ab8 436
437 // validate security token
438 //
2cefa62a 439 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 440
4dfb9db7 441 /*
442 * Set $default_charset to correspond with the user's selection
443 * of language interface.
444 */
445 set_my_charset();
b7ff469f 446 if (! deliverMessage($composeMessage, true)) {
da95c4b6 447 showInputForm($session);
00793a25 448 exit();
734f4ee6 449 } else {
00793a25 450 $draft_message = _("Draft Email Saved");
451 /* If this is a resumed draft, then delete the original */
452 if(isset($delete_draft)) {
a9805897 453 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options);
b034bca2 454 sqimap_mailbox_select($imap_stream, $draft_folder);
455 // force bypass_trash=true because message should be saved when deliverMessage() returns true.
91c27aee 456 // in current implementation of sqimap_msgs_list_flag() single message id can
b034bca2 457 // be submitted as string. docs state that it should be array.
458 sqimap_msgs_list_delete($imap_stream, $draft_folder, $delete_draft, true);
459 if ($auto_expunge) {
460 sqimap_mailbox_expunge($imap_stream, $draft_folder, true);
9c3e6cd4 461 }
b034bca2 462 sqimap_logout($imap_stream);
463 }
1638beb6 464
762853f4 465 $oErrorHandler->saveDelayedErrors();
c077ffeb 466 session_write_close();
762853f4 467
b034bca2 468 if ($compose_new_win == '1') {
09047d19 469 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 470 header("Location: $location/compose.php?saved_draft=yes&session=$composesession");
09047d19 471 } else {
c8dc86c9 472//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 473 echo ' <br><br><div style="text-align: center;"><a href="' . $location
09047d19 474 . '/compose.php?saved_sent=yes&amp;session=' . $composesession . '">'
f265009a 475 . _("Return") . '</a></div>';
a6d3eff6 476 }
b034bca2 477 exit();
478 } else {
09047d19 479 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 480 header("Location: $location/right_main.php?mailbox=" . urlencode($draft_folder) .
b034bca2 481 "&startMessage=1&note=".urlencode($draft_message));
09047d19 482 } else {
c8dc86c9 483//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 484 echo ' <br><br><div style="text-align: center;"><a href="' . $location
09047d19 485 . '/right_main.php?mailbox=' . urlencode($draft_folder)
486 . '&amp;startMessage=1&amp;note=' . urlencode($draft_message) .'">'
f265009a 487 . _("Return") . '</a></div>';
a6d3eff6 488 }
b034bca2 489 exit();
00793a25 490 }
491 }
492}
493
4dfb9db7 494if ($send) {
199a9ab8 495
496 // validate security token
497 //
2cefa62a 498 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 499
0b97a708 500 if (isset($_FILES['attachfile']) &&
73ad81bf 501 $_FILES['attachfile']['tmp_name'] &&
502 $_FILES['attachfile']['tmp_name'] != 'none') {
da95c4b6 503 $AttachFailure = saveAttachedFiles($session);
00793a25 504 }
d887e067 505
00793a25 506 if (checkInput(false) && !isset($AttachFailure)) {
73ad81bf 507 if ($mailbox == "All Folders") {
508 /* We entered compose via the search results page */
a42c236f 509 $mailbox = 'INBOX'; /* Send 'em to INBOX, that's safe enough */
73ad81bf 510 }
9a19cc66 511 $urlMailbox = urlencode($mailbox);
3f6b1b6f 512 if (! isset($passed_id)) {
513 $passed_id = 0;
00793a25 514 }
d4c5c50c 515 /**
00793a25 516 * Set $default_charset to correspond with the user's selection
7058a2a9 517 * of language interface.
00793a25 518 */
519 set_my_charset();
d4c5c50c 520 /**
00793a25 521 * This is to change all newlines to \n
7058a2a9 522 * We'll change them to \r\n later (in the sendMessage function)
00793a25 523 */
524 $body = str_replace("\r\n", "\n", $body);
525 $body = str_replace("\r", "\n", $body);
526
d4c5c50c 527 /**
18c9998a 528 * Rewrap $body so that no line is bigger than $editor_size
00793a25 529 */
18c9998a 530 $body = explode("\n", $body);
531 $newBody = '';
532 foreach ($body as $line) {
533 if( $line <> '-- ' ) {
73ad81bf 534 $line = rtrim($line);
18c9998a 535 }
774d79cc 536 if (sq_strlen($line, $default_charset) <= $editor_size + 1) {
18c9998a 537 $newBody .= $line . "\n";
538 } else {
774d79cc 539 sqWordWrap($line, $editor_size, $default_charset);
18c9998a 540 $newBody .= $line . "\n";
541
542 }
543
544 }
545 $body = $newBody;
1c044820 546
a91189d6 547 $Result = deliverMessage($composeMessage);
81de00c0 548
64793f9a 549 if ($Result)
550 $mail_sent = 'yes';
551 else
552 $mail_sent = 'no';
553
1638beb6 554 // NOTE: this hook changed in 1.5.2 from sending $Result and
6e515418 555 // $composeMessage as args #2 and #3 to being in an array
556 // under arg #2
802e7490 557 $temp = array(&$Result, &$composeMessage, &$mail_sent);
558 do_hook('compose_send_after', $temp);
00793a25 559 if (! $Result) {
da95c4b6 560 showInputForm($session);
00793a25 561 exit();
562 }
5c4ff7bf 563
b034bca2 564 /* if it is resumed draft, delete draft message */
00793a25 565 if ( isset($delete_draft)) {
a9805897 566 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options);
b034bca2 567 sqimap_mailbox_select($imap_stream, $draft_folder);
568 // bypass_trash=true because message should be saved when deliverMessage() returns true.
91c27aee 569 // in current implementation of sqimap_msgs_list_flag() single message id can
b034bca2 570 // be submitted as string. docs state that it should be array.
571 sqimap_msgs_list_delete($imap_stream, $draft_folder, $delete_draft, true);
572 if ($auto_expunge) {
573 sqimap_mailbox_expunge($imap_stream, $draft_folder, true);
574 }
575 sqimap_logout($imap_stream);
00793a25 576 }
81de00c0 577 /*
578 * Store the error array in the session because they will be lost on a redirect
579 */
762853f4 580 $oErrorHandler->saveDelayedErrors();
c077ffeb 581 session_write_close();
762853f4 582
9c3e6cd4 583 if ($compose_new_win == '1') {
09047d19 584 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
39cf816f 585 header("Location: $location/compose.php?mail_sent=$mail_sent");
09047d19 586 } else {
c8dc86c9 587//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 588 echo ' <br><br><div style="text-align: center;"><a href="' . $location
64793f9a 589 . '/compose.php?mail_sent=$mail_sent">'
f265009a 590 . _("Return") . '</a></div>';
09047d19 591 }
592 exit();
593 } else {
594 if ( !isset($pageheader_sent) || !$pageheader_sent ) {
5594db7a 595 global $return_to_message_after_reply;
aa1340eb 596 if (($action === 'reply' || $action === 'reply_all' || $action === 'forward' || $action === 'forward_as_attachment')
597 && $return_to_message_after_reply && $passed_id)
5594db7a 598 header("Location: $location/read_body.php?passed_id=$passed_id&mailbox=$urlMailbox".
599 "&startMessage=$startMessage&mail_sent=$mail_sent");
600 else
601 header("Location: $location/right_main.php?mailbox=$urlMailbox".
602 "&startMessage=$startMessage&mail_sent=$mail_sent");
09047d19 603 } else {
c8dc86c9 604//FIXME: DON'T ECHO HTML FROM CORE!
f265009a 605 echo ' <br><br><div style="text-align: center;"><a href="' . $location
09047d19 606 . "/right_main.php?mailbox=$urlMailbox"
64793f9a 607 . "&amp;startMessage=$startMessage&amp;mail_sent=$mail_sent\">"
f265009a 608 . _("Return") . '</a></div>';
09047d19 609 }
610 exit();
9c3e6cd4 611 }
734f4ee6 612 } else {
9c3e6cd4 613 if ($compose_new_win == '1') {
614 compose_Header($color, $mailbox);
615 }
616 else {
617 displayPageHeader($color, $mailbox);
618 }
00793a25 619 if (isset($AttachFailure)) {
73ad81bf 620 plain_error_message(_("Could not move/copy file. File not attached"),
621 $color);
00793a25 622 }
00793a25 623 checkInput(true);
da95c4b6 624 showInputForm($session);
00793a25 625 /* sqimap_logout($imapConnection); */
626 }
e02775fe 627} elseif (isset($html_addr_search_done)) {
199a9ab8 628
629 // validate security token
630 //
2cefa62a 631 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 632
73ad81bf 633 if ($compose_new_win == '1') {
634 compose_Header($color, $mailbox);
635 }
636 else {
637 displayPageHeader($color, $mailbox);
638 }
00793a25 639
640 if (isset($send_to_search) && is_array($send_to_search)) {
641 foreach ($send_to_search as $k => $v) {
642 if (substr($k, 0, 1) == 'T') {
643 if ($send_to) {
644 $send_to .= ', ';
645 }
646 $send_to .= $v;
647 }
648 elseif (substr($k, 0, 1) == 'C') {
649 if ($send_to_cc) {
650 $send_to_cc .= ', ';
651 }
652 $send_to_cc .= $v;
653 }
654 elseif (substr($k, 0, 1) == 'B') {
655 if ($send_to_bcc) {
656 $send_to_bcc .= ', ';
657 }
658 $send_to_bcc .= $v;
659 }
660 }
661 }
da95c4b6 662 showInputForm($session);
167c6996 663} elseif (isset($html_addr_search) && !isset($html_addr_search_cancel)) {
0b97a708 664 if (isset($_FILES['attachfile']) &&
73ad81bf 665 $_FILES['attachfile']['tmp_name'] &&
666 $_FILES['attachfile']['tmp_name'] != 'none') {
0b97a708 667 if(saveAttachedFiles($session)) {
cb34dbd0 668 plain_error_message(_("Could not move/copy file. File not attached"));
00793a25 669 }
670 }
671 /*
672 * I am using an include so as to elminiate an extra unnecessary
673 * click. If you can think of a better way, please implement it.
674 */
675 include_once('./addrbook_search_html.php');
e02775fe 676} elseif (isset($attach)) {
199a9ab8 677
678 // validate security token
679 //
2cefa62a 680 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 681
73ad81bf 682 if ($compose_new_win == '1') {
683 compose_Header($color, $mailbox);
684 } else {
685 displayPageHeader($color, $mailbox);
686 }
5a3e52f3 687 if (saveAttachedFiles($session)) {
cb34dbd0 688 plain_error_message(_("Could not move/copy file. File not attached"));
5a3e52f3 689 }
da95c4b6 690 showInputForm($session);
01265fba 691}
692elseif (isset($sigappend)) {
199a9ab8 693
694 // validate security token
695 //
2cefa62a 696 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 697
1e2a6ff6 698 $signature = $idents[$identity]['signature'];
699
01265fba 700 $body .= "\n\n".($prefix_sig==true? "-- \n":'').$signature;
701 if ($compose_new_win == '1') {
73ad81bf 702 compose_Header($color, $mailbox);
01265fba 703 } else {
704 displayPageHeader($color, $mailbox);
705 }
da95c4b6 706 showInputForm($session);
e02775fe 707} elseif (isset($do_delete)) {
199a9ab8 708
709 // validate security token
710 //
2cefa62a 711 sm_validate_security_token($submitted_token, -1, TRUE);
199a9ab8 712
73ad81bf 713 if ($compose_new_win == '1') {
714 compose_Header($color, $mailbox);
715 } else {
716 displayPageHeader($color, $mailbox);
717 }
00793a25 718
00793a25 719 if (isset($delete) && is_array($delete)) {
720 foreach($delete as $index) {
a58b05b4 721 if (!empty($composeMessage->entities) && isset($composeMessage->entities[$index])) {
c077ffeb 722 $composeMessage->entities[$index]->purgeAttachments();
16449d84 723 // FIXME: one person reported that unset() didn't do anything at all here, so this is a work-around... but it triggers PHP notices if the unset() doesn't work, which should be fixed... but bigger question is if unset() doesn't work here, what about everywhere else? Anyway, uncomment this if you think you need it
724 //$composeMessage->entities[$index] = NULL;
a58b05b4 725 unset ($composeMessage->entities[$index]);
726 }
a91189d6 727 }
728 $new_entities = array();
729 foreach ($composeMessage->entities as $entity) {
730 $new_entities[] = $entity;
00793a25 731 }
a91189d6 732 $composeMessage->entities = $new_entities;
00793a25 733 }
da95c4b6 734 showInputForm($session);
734f4ee6 735} else {
00793a25 736 /*
737 * This handles the default case as well as the error case
1c044820 738 * (they had the same code) --> if (isset($smtpErrors))
00793a25 739 */
44560457 740
741 if ($compose_new_win == '1') {
73ad81bf 742 compose_Header($color, $mailbox);
44560457 743 } else {
73ad81bf 744 displayPageHeader($color, $mailbox);
44560457 745 }
00793a25 746
747 $newmail = true;
748
a61878d0 749 if (!isset($passed_ent_id)) {
750 $passed_ent_id = '';
751 }
752 if (!isset($passed_id)) {
1c044820 753 $passed_id = '';
a61878d0 754 }
755 if (!isset($mailbox)) {
756 $mailbox = '';
1c044820 757 }
a61878d0 758 if (!isset($action)) {
759 $action = '';
760 }
1c044820 761
44560457 762 $values = newMail($mailbox,$passed_id,$passed_ent_id, $action, $session);
b9928adc 763
f2ad47f1 764 // forward as attachment - subject is in the message in session
765 //
766 if ($action == 'forward_as_attachment' && empty($values['subject']))
767 $subject = $composeMessage->rfc822_header->subject;
768
b9928adc 769 /* in case the origin is not read_body.php */
770 if (isset($send_to)) {
73ad81bf 771 $values['send_to'] = $send_to;
b9928adc 772 }
773 if (isset($send_to_cc)) {
73ad81bf 774 $values['send_to_cc'] = $send_to_cc;
b9928adc 775 }
776 if (isset($send_to_bcc)) {
73ad81bf 777 $values['send_to_bcc'] = $send_to_bcc;
b9928adc 778 }
2a2f2185 779 if (isset($subject)) {
73ad81bf 780 $values['subject'] = $subject;
2a2f2185 781 }
79cecc00 782 if (isset($mailprio)) {
783 $values['mailprio'] = $mailprio;
784 }
785 if (isset($orig_identity)) {
786 $values['identity'] = $orig_identity;
787 }
41b94d65 788 showInputForm($session, $values);
00793a25 789}
790
791exit();
792
00793a25 793/**************** Only function definitions go below *************/
794
92c6f757 795function getforwardSubject($subject)
796{
797 if ((substr(strtolower($subject), 0, 4) != 'fwd:') &&
73ad81bf 798 (substr(strtolower($subject), 0, 5) != '[fwd:') &&
799 (substr(strtolower($subject), 0, 6) != '[ fwd:')) {
92c6f757 800 $subject = '[Fwd: ' . $subject . ']';
801 }
802 return $subject;
803}
00793a25 804
48985d59 805/* This function is used when not sending or adding attachments */
44560457 806function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $session='') {
1e2a6ff6 807 global $editor_size, $default_use_priority, $body, $idents,
ce68b76b 808 $use_signature, $data_dir, $username,
a9805897 809 $key, $imapServerAddress, $imapPort, $imap_stream_options,
74f66d27 810 $composeMessage, $body_quote, $request_mdn, $request_dr,
856e58ef 811 $mdn_user_support, $languages, $squirrelmail_language,
7b2092f1 812 $default_charset, $do_not_reply_to_self, $compose_messages;
e7f1a81d 813
d4f20027 814 /*
815 * Set $default_charset to correspond with the user's selection
816 * of language interface. $default_charset global is not correct,
817 * if message is composed in new window.
818 */
819 set_my_charset();
820
91f2085b 821 $send_to = $send_to_cc = $send_to_bcc = $subject = $identity = '';
bdb92db3 822 $mailprio = 3;
44560457 823
41b94d65 824 if ($passed_id) {
906f7e9f 825 $imapConnection = sqimap_login($username, false, $imapServerAddress,
a9805897 826 $imapPort, 0, $imap_stream_options);
a61878d0 827
48985d59 828 sqimap_mailbox_select($imapConnection, $mailbox);
41b94d65 829 $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
1c044820 830
a61878d0 831 $body = '';
832 if ($passed_ent_id) {
833 /* redefine the messsage in case of message/rfc822 */
834 $message = $message->getEntity($passed_ent_id);
835 /* message is an entity which contains the envelope and type0=message
73ad81bf 836 * and type1=rfc822. The actual entities are childs from
837 * $message->entities[0]. That's where the encoding and is located
838 */
a61878d0 839
840 $entities = $message->entities[0]->findDisplayEntity
73ad81bf 841 (array(), $alt_order = array('text/plain'));
a61878d0 842 if (!count($entities)) {
843 $entities = $message->entities[0]->findDisplayEntity
9c462f8b 844 (array(), $alt_order = array('text/plain','text/html'));
a61878d0 845 }
846 $orig_header = $message->rfc822_header; /* here is the envelope located */
847 /* redefine the message for picking up the attachments */
848 $message = $message->entities[0];
849
850 } else {
851 $entities = $message->findDisplayEntity (array(), $alt_order = array('text/plain'));
852 if (!count($entities)) {
9c462f8b 853 $entities = $message->findDisplayEntity (array(), $alt_order = array('text/plain','text/html'));
a61878d0 854 }
855 $orig_header = $message->rfc822_header;
856 }
1c044820 857
a61878d0 858 $type0 = $message->type0;
859 $type1 = $message->type1;
41b94d65 860 foreach ($entities as $ent) {
b455e47b 861 $msg = $message->getEntity($ent);
862 $type0 = $msg->type0;
863 $type1 = $msg->type1;
a61878d0 864 $unencoded_bodypart = mime_fetch_body($imapConnection, $passed_id, $ent);
865 $body_part_entity = $message->getEntity($ent);
1638beb6 866 $bodypart = decodeBody($unencoded_bodypart,
73ad81bf 867 $body_part_entity->header->encoding);
a61878d0 868 if ($type1 == 'html') {
5b755d9f 869 $bodypart = str_replace("\n", ' ', $bodypart);
bb977394 870 $bodypart = preg_replace(array('/<\/?p>/i','/<div><\/div>/i','/<br\s*(\/)*>/i','/<\/?div>/i'), "\n", $bodypart);
5b755d9f 871 $bodypart = str_replace(array('&nbsp;','&gt;','&lt;'),array(' ','>','<'),$bodypart);
a61878d0 872 $bodypart = strip_tags($bodypart);
873 }
e842b215 874 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
73ad81bf 875 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode')) {
e842b215 876 if (mb_detect_encoding($bodypart) != 'ASCII') {
f4bb5d22 877 $bodypart = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode', $bodypart);
e842b215 878 }
879 }
eceefdfe 880
bfa54da7 881 // charset encoding in compose form stuff
73ad81bf 882 if (isset($body_part_entity->header->parameters['charset'])) {
883 $actual = $body_part_entity->header->parameters['charset'];
884 } else {
885 $actual = 'us-ascii';
886 }
beca818e 887
73ad81bf 888 if ( $actual && is_conversion_safe($actual) && $actual != $default_charset){
889 $bodypart = charset_convert($actual,$bodypart,$default_charset,false);
890 }
bfa54da7 891 // end of charset encoding in compose
eceefdfe 892
a61878d0 893 $body .= $bodypart;
894 }
895 if ($default_use_priority) {
896 $mailprio = substr($orig_header->priority,0,1);
897 if (!$mailprio) {
898 $mailprio = 3;
899 }
900 } else {
901 $mailprio = '';
902 }
bdb92db3 903
a45887d7 904 $from_o = $orig_header->from;
fe868193 905 if (is_array($from_o)) {
906 if (isset($from_o[0])) {
907 $from_o = $from_o[0];
908 }
909 }
bdb92db3 910 if (is_object($from_o)) {
911 $orig_from = $from_o->getAddress();
912 } else {
913 $orig_from = '';
a61878d0 914 }
1e2a6ff6 915
a91189d6 916 $identities = array();
1e2a6ff6 917 if (count($idents) > 1) {
918 foreach($idents as $nr=>$data) {
919 $enc_from_name = '"'.$data['full_name'].'" <'. $data['email_address'].'>';
a91189d6 920 $identities[] = $enc_from_name;
921 }
1e2a6ff6 922
a91189d6 923 $identity_match = $orig_header->findAddress($identities);
ea721316 924 if ($identity_match !== FALSE) {
a91189d6 925 $identity = $identity_match;
a61878d0 926 }
bdb92db3 927 }
a61878d0 928
929 switch ($action) {
73ad81bf 930 case ('draft'):
931 $use_signature = FALSE;
932 $composeMessage->rfc822_header = $orig_header;
933 $send_to = decodeHeader($orig_header->getAddr_s('to'),false,false,true);
934 $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'),false,false,true);
935 $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'),false,false,true);
936 $send_from = $orig_header->getAddr_s('from');
937 $send_from_parts = new AddressStructure();
938 $send_from_parts = $orig_header->parseAddress($send_from);
939 $send_from_add = $send_from_parts->mailbox . '@' . $send_from_parts->host;
40e07136 940 $identity = find_identity(array($send_from_add));
73ad81bf 941 $subject = decodeHeader($orig_header->subject,false,false,true);
1638beb6 942
762853f4 943 // Remember the receipt settings
944 $request_mdn = $mdn_user_support && !empty($orig_header->dnt) ? '1' : '0';
945 $request_dr = $mdn_user_support && !empty($orig_header->drnt) ? '1' : '0';
1638beb6 946
73ad81bf 947 /* remember the references and in-reply-to headers in case of an reply */
657fe1bd 948//FIXME: it would be better to fiddle with headers inside of the message object or possibly when delivering the message to its destination (drafts folder?); is this possible?
73ad81bf 949 $composeMessage->rfc822_header->more_headers['References'] = $orig_header->references;
950 $composeMessage->rfc822_header->more_headers['In-Reply-To'] = $orig_header->in_reply_to;
951 // rewrap the body to clean up quotations and line lengths
952 sqBodyWrap($body, $editor_size);
953 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
aff28a6d 954 if (!empty($orig_header->x_sm_flag_reply))
955 $composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply'] = $orig_header->x_sm_flag_reply;
041d360b 956//TODO: completely unclear if should be using $compose_session instead of $session below
957 $compose_messages[$session] = $composeMessage;
958 sqsession_register($compose_messages,'compose_messages');
73ad81bf 959 break;
960 case ('edit_as_new'):
961 $send_to = decodeHeader($orig_header->getAddr_s('to'),false,false,true);
962 $send_to_cc = decodeHeader($orig_header->getAddr_s('cc'),false,false,true);
963 $send_to_bcc = decodeHeader($orig_header->getAddr_s('bcc'),false,false,true);
964 $subject = decodeHeader($orig_header->subject,false,false,true);
965 $mailprio = $orig_header->priority;
966 $orig_from = '';
967 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
968 // rewrap the body to clean up quotations and line lengths
969 sqBodyWrap($body, $editor_size);
970 break;
971 case ('forward'):
972 $send_to = '';
973 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
974 $body = getforwardHeader($orig_header) . $body;
975 // the logic for calling sqUnWordWrap here would be to allow the browser to wrap the lines
976 // forwarded message text should be as undisturbed as possible, so commenting out this call
977 // sqUnWordWrap($body);
978 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
91c27aee 979
73ad81bf 980 //add a blank line after the forward headers
981 $body = "\n" . $body;
982 break;
983 case ('forward_as_attachment'):
984 $subject = getforwardSubject(decodeHeader($orig_header->subject,false,false,true));
985 $composeMessage = getMessage_RFC822_Attachment($message, $composeMessage, $passed_id, $passed_ent_id, $imapConnection);
f2ad47f1 986 $subject = decodeHeader($orig_header->subject,false,false,true);
987 $subject = str_replace('"', "'", $subject);
988 $subject = trim($subject);
989 if (substr(strtolower($subject), 0, 4) != 'fwd:') {
990 $subject = 'Fwd: ' . $subject;
991 }
73ad81bf 992 $body = '';
993 break;
994 case ('reply_all'):
995 if(isset($orig_header->mail_followup_to) && $orig_header->mail_followup_to) {
996 $send_to = $orig_header->getAddr_s('mail_followup_to');
b268e66b 997 } else {
73ad81bf 998 $send_to_cc = replyAllString($orig_header);
999 $send_to_cc = decodeHeader($send_to_cc,false,false,true);
a9b9e5d3 1000 $send_to_cc = str_replace('""', '"', $send_to_cc);
b268e66b 1001 }
73ad81bf 1002 case ('reply'):
1003 // skip this if send_to was already set right above here
1004 if(!$send_to) {
1005 $send_to = $orig_header->reply_to;
1006 if (is_array($send_to) && count($send_to)) {
a9b9e5d3 1007 $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
73ad81bf 1008 } else if (is_object($send_to)) { /* unneccesarry, just for failsafe purpose */
a9b9e5d3 1009 $send_to = $orig_header->getAddr_s('reply_to', ',', FALSE, TRUE);
73ad81bf 1010 } else {
a9b9e5d3 1011 $send_to = $orig_header->getAddr_s('from', ',', FALSE, TRUE);
73ad81bf 1012 }
dd4a44cd 1013 }
73ad81bf 1014 $send_to = decodeHeader($send_to,false,false,true);
a9b9e5d3 1015 $send_to = str_replace('""', '"', $send_to);
ace75dcb 1016
1017
1018 // If user doesn't want replies to her own messages
1019 // going back to herself (instead send again to the
1020 // original recipient of the message being replied to),
1021 // then iterate through identities, checking if the TO
1022 // field is one of them (if the reply is to ourselves)
1023 //
1024 // Note we don't bother if the original message doesn't
1025 // have anything in the TO field itself (because that's
1026 // what we use if we change the recipient to be that of
1027 // the previous message)
1028 //
1029 if ($do_not_reply_to_self && !empty($orig_header->to)) {
1030
1031 $orig_to = '';
1032
1033 foreach($idents as $id) {
1034
1035 if (!empty($id['email_address'])
1036 && strpos($send_to, $id['email_address']) !== FALSE) {
1037
1038 // if this is a reply-all, the original recipient
1039 // is already in the CC field, so we can just blank
1040 // the recipient (TO field) (as long as the CC field
a9b6e52d 1041 // isn't empty that is)... but then move the CC into
1042 // the TO, so TO isn't empty
ace75dcb 1043 //
6fac6196 1044 if ($action == 'reply_all' && !empty($send_to_cc)) {
a9b6e52d 1045 $orig_to = $send_to_cc;
1046 $send_to_cc = '';
ace75dcb 1047 break;
1048 }
1049
1050 $orig_to = $orig_header->to;
1051 if (is_array($orig_to) && count($orig_to)) {
1052 $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE);
1053 } else if (is_object($orig_to)) { /* unneccesarry, just for failsafe purpose */
1054 $orig_to = $orig_header->getAddr_s('to', ',', FALSE, TRUE);
1055 } else {
1056 $orig_to = '';
1057 }
1058 $orig_to = decodeHeader($orig_to,false,false,true);
1059 $orig_to = str_replace('""', '"', $orig_to);
1060
1061 break;
1062 }
1063 }
1064
1065 // if the reply was addressed back to ourselves,
5df2efa2 1066 // we will send it to the TO of the previous message
ace75dcb 1067 //
1068 if (!empty($orig_to)) {
1069
5df2efa2 1070 $send_to = $orig_to;
5777c73d 1071
1072 // in this case, we also want to reset the FROM
1073 // identity as well (it should match the original
1074 // *FROM* header instead of TO or CC)
1075 //
1076 if (count($idents) > 1) {
1077 $identity = '';
1078 foreach($idents as $i => $id) {
1079 if (!empty($id['email_address'])
1080 && strpos($orig_from, $id['email_address']) !== FALSE) {
1081 $identity = $i;
1082 break;
1083 }
1084 }
1085 }
1086
ace75dcb 1087 }
1088
1089 }
1090
1091
73ad81bf 1092 $subject = decodeHeader($orig_header->subject,false,false,true);
1093 $subject = str_replace('"', "'", $subject);
1094 $subject = trim($subject);
1095 if (substr(strtolower($subject), 0, 3) != 're:') {
1096 $subject = 'Re: ' . $subject;
1097 }
1098 /* this corrects some wrapping/quoting problems on replies */
1099 $rewrap_body = explode("\n", $body);
3aaa3214 1100 $from = (is_array($orig_header->from) && !empty($orig_header->from)) ? $orig_header->from[0] : $orig_header->from;
73ad81bf 1101 $body = '';
1102 $strip_sigs = getPref($data_dir, $username, 'strip_sigs');
1103 foreach ($rewrap_body as $line) {
3673a2de 1104 if ($strip_sigs && rtrim($line, "\r\n") == '-- ') {
73ad81bf 1105 break;
1106 }
1107 if (preg_match("/^(>+)/", $line, $matches)) {
1108 $gt = $matches[1];
1109 $body .= $body_quote . str_replace("\n", "\n$body_quote$gt ", rtrim($line)) ."\n";
1110 } else {
1111 $body .= $body_quote . (!empty($body_quote) ? ' ' : '') . str_replace("\n", "\n$body_quote" . (!empty($body_quote) ? ' ' : ''), rtrim($line)) . "\n";
1112 }
a61878d0 1113 }
c9d61baf 1114
73ad81bf 1115 //rewrap the body to clean up quotations and line lengths
1116 $body = sqBodyWrap ($body, $editor_size);
c9d61baf 1117
73ad81bf 1118 $body = getReplyCitation($from , $orig_header->date) . $body;
1119 $composeMessage->reply_rfc822_header = $orig_header;
12a0ed01 1120
73ad81bf 1121 break;
1122 default:
1123 break;
41b94d65 1124 }
b4e7df34 1125//FIXME: we used to register $compose_messages in the session here, but not any more - so do we still need the session_write_close() and sqimap_logout() here? We probably need the IMAP logout, but what about the session closure?
5da08ef7 1126 session_write_close();
a61878d0 1127 sqimap_logout($imapConnection);
41b94d65 1128 }
a61878d0 1129 $ret = array( 'send_to' => $send_to,
73ad81bf 1130 'send_to_cc' => $send_to_cc,
1131 'send_to_bcc' => $send_to_bcc,
1132 'subject' => $subject,
1133 'mailprio' => $mailprio,
1134 'body' => $body,
1135 'identity' => $identity );
a61878d0 1136
41b94d65 1137 return ($ret);
48985d59 1138} /* function newMail() */
1139
50706f77 1140/**
1141 * downloads attachments from original message, stores them in attachment directory and adds
1142 * them to composed message.
1143 * @param object $message
1144 * @param object $composeMessage
1145 * @param integer $passed_id
1146 * @param mixed $entities
1147 * @param mixed $imapConnection
91c27aee 1148 * @return object
50706f77 1149 */
a43e4b90 1150function getAttachments($message, &$composeMessage, $passed_id, $entities, $imapConnection) {
1f270d3c 1151 global $squirrelmail_language, $languages, $username, $attachment_dir;
628bce99 1152
1c044820 1153 if (!count($message->entities) ||
73ad81bf 1154 ($message->type0 == 'message' && $message->type1 == 'rfc822')) {
41b94d65 1155 if ( !in_array($message->entity_id, $entities) && $message->entity_id) {
73ad81bf 1156 switch ($message->type0) {
1157 case 'message':
1158 if ($message->type1 == 'rfc822') {
1159 $filename = $message->rfc822_header->subject;
1160 if ($filename == "") {
1161 $filename = "untitled-".$message->entity_id;
1162 }
6f71f6e6 1163 $filename .= '.eml';
73ad81bf 1164 } else {
1165 $filename = $message->getFilename();
181538ac 1166 }
73ad81bf 1167 break;
1168 default:
1169 if (!$message->mime_header) { /* temporary hack */
1170 $message->mime_header = $message->header;
1171 }
1172 $filename = $message->getFilename();
1173 break;
1174 }
117aa0c5 1175//FIXME: added three args to the following, so as to set the last one to TRUE, to mimick a fix in 1.4.21 (#2994865), but didn't test this (note that in 1.4.21, the 2nd and 3rd args are FALSE, but here in this code, they weren't being specified (thus defaulting to TRUE), so I don't know if that means this code is outdated and should have been changed to FALSE, FALSE or if this code is completely different and the addition of the TRUE for arg #4 is wrong
1176 $filename = str_replace('&#32;', ' ', decodeHeader($filename, true, true, true));
73ad81bf 1177 if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
1178 function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode')) {
f4bb5d22 1179 $filename = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_encode', $filename);
73ad81bf 1180 }
1f270d3c 1181
1182 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1183 $localfilename = sq_get_attach_tempfile();
1184 $message->att_local_name = $localfilename;
73ad81bf 1185
1186 $composeMessage->initAttachment($message->type0.'/'.$message->type1,$filename,
628bce99 1187 $localfilename);
73ad81bf 1188
1189 /* Write Attachment to file */
1f270d3c 1190 $fp = fopen ($hashed_attachment_dir . '/' . $localfilename, 'wb');
91c27aee 1191 mime_print_body_lines ($imapConnection, $passed_id, $message->entity_id, $message->header->encoding, $fp);
73ad81bf 1192 fclose ($fp);
48985d59 1193 }
734f4ee6 1194 } else {
a43e4b90 1195 for ($i=0, $entCount=count($message->entities); $i<$entCount;$i++) {
1196 $composeMessage=getAttachments($message->entities[$i], $composeMessage, $passed_id, $entities, $imapConnection);
48985d59 1197 }
1198 }
a43e4b90 1199 return $composeMessage;
48985d59 1200}
1201
1c044820 1202function getMessage_RFC822_Attachment($message, $composeMessage, $passed_id,
73ad81bf 1203 $passed_ent_id='', $imapConnection) {
756406df 1204 if (!$passed_ent_id) {
1c044820 1205 $body_a = sqimap_run_command($imapConnection,
73ad81bf 1206 'FETCH '.$passed_id.' RFC822',
1207 TRUE, $response, $readmessage,
1208 TRUE);
756406df 1209 } else {
1c044820 1210 $body_a = sqimap_run_command($imapConnection,
73ad81bf 1211 'FETCH '.$passed_id.' BODY['.$passed_ent_id.']',
1212 TRUE, $response, $readmessage, TRUE);
a61878d0 1213 $message = $message->parent;
756406df 1214 }
d0519c03 1215 if ($response == 'OK') {
a61878d0 1216 $subject = encodeHeader($message->rfc822_header->subject);
1217 array_shift($body_a);
1c044820 1218 array_pop($body_a);
a61878d0 1219 $body = implode('', $body_a) . "\r\n";
1c044820 1220
1f270d3c 1221 global $username, $attachment_dir;
1222 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1223 $localfilename = sq_get_attach_tempfile();
1f270d3c 1224 $fp = fopen($hashed_attachment_dir . '/' . $localfilename, 'wb');
a61878d0 1225 fwrite ($fp, $body);
1226 fclose($fp);
6f71f6e6 1227 $composeMessage->initAttachment('message/rfc822',$subject.'.eml',
628bce99 1228 $localfilename);
a43e4b90 1229 }
1230 return $composeMessage;
a6ec592e 1231}
1232
41b94d65 1233function showInputForm ($session, $values=false) {
856e58ef 1234 global $send_to, $send_to_cc, $send_to_bcc,
f8eb968d 1235 $body, $startMessage, $action, $attachments,
b2b614bb 1236 $use_signature, $signature, $prefix_sig, $session_expired,
8d8da447 1237 $editor_size, $editor_height, $subject, $newmail,
e506b6e5 1238 $use_javascript_addr_book, $passed_id, $mailbox, $fwduid,
73ad81bf 1239 $from_htmladdr_search, $location_of_buttons, $attachment_dir,
ce68b76b 1240 $username, $data_dir, $identity, $idents, $delete_draft,
1241 $mailprio, $compose_new_win, $saved_draft, $mail_sent, $sig_first,
b4e7df34 1242 $composeMessage, $composesession, $default_charset,
762853f4 1243 $compose_onsubmit, $oTemplate, $oErrorHandler;
a43e4b90 1244
87745b9c 1245 if (checkForJavascript()) {
1246 $onfocus = ' onfocus="alreadyFocused=true;"';
1247 $onfocus_array = array('onfocus' => 'alreadyFocused=true;');
1248 }
1249 else {
1250 $onfocus = '';
1251 $onfocus_array = array();
1252 }
1253
41b94d65 1254 if ($values) {
73ad81bf 1255 $send_to = $values['send_to'];
1256 $send_to_cc = $values['send_to_cc'];
1257 $send_to_bcc = $values['send_to_bcc'];
1258 $subject = $values['subject'];
1259 $mailprio = $values['mailprio'];
1260 $body = $values['body'];
1261 $identity = (int) $values['identity'];
676bb189 1262 } else {
73ad81bf 1263 $send_to = decodeHeader($send_to, true, false);
1264 $send_to_cc = decodeHeader($send_to_cc, true, false);
1265 $send_to_bcc = decodeHeader($send_to_bcc, true, false);
41b94d65 1266 }
1c044820 1267
48985d59 1268 if ($use_javascript_addr_book) {
c8dc86c9 1269//FIXME: NO HTML IN CORE!
2c92ea9d 1270 echo "\n". '<script type="text/javascript">'."\n<!--\n" .
73ad81bf 1271 'function open_abook() { ' . "\n" .
1272 ' var nwin = window.open("addrbook_popup.php","abookpopup",' .
1273 '"width=670,height=300,resizable=yes,scrollbars=yes");' . "\n" .
1274 ' if((!nwin.opener) && (document.windows != null))' . "\n" .
1275 ' nwin.opener = document.windows;' . "\n" .
1276 "}\n" .
1277 "// -->\n</script>\n\n";
48985d59 1278 }
1279
c8dc86c9 1280//FIXME: NO HTML IN CORE!
4a1788b3 1281 echo "\n" . '<form name="compose" action="compose.php" method="post" ' .
73ad81bf 1282 'enctype="multipart/form-data"';
a34b07a5 1283
1284 $compose_onsubmit = array();
6e515418 1285 global $null;
1286 do_hook('compose_form', $null);
1c044820 1287
a34b07a5 1288 // Plugins that use compose_form hook can add an array entry
1289 // to the globally scoped $compose_onsubmit; we add them up
5c4ff7bf 1290 // here and format the form tag's full onsubmit handler.
1291 // Each plugin should use "return false" if they need to
a34b07a5 1292 // stop form submission but otherwise should NOT use "return
1293 // true" to give other plugins the chance to do what they need
1294 // to do; SquirrelMail itself will add the final "return true".
1295 // Onsubmit text is enclosed inside of double quotes, so plugins
1296 // need to quote accordingly.
395c3216 1297 //
1298 // Also, plugin authors should try to retain compatibility with
1299 // the Compose Extras plugin by resetting its compose submit
1300 // counter when preventing form submit. Use this code:
1301 // if (your-code-here) { submit_count = 0; return false; }
1302 //
a34b07a5 1303 if (checkForJavascript()) {
5c4ff7bf 1304 if (empty($compose_onsubmit))
a34b07a5 1305 $compose_onsubmit = array();
5c4ff7bf 1306 else if (!is_array($compose_onsubmit))
a34b07a5 1307 $compose_onsubmit = array($compose_onsubmit);
1308
82dcbb1e 1309 $onsubmit_text = '';
a34b07a5 1310 foreach ($compose_onsubmit as $text) {
1311 $text = trim($text);
82dcbb1e 1312 if (!empty($text)) {
1313 if (substr($text, -1) != ';' && substr($text, -1) != '}')
1314 $text .= '; ';
1315 $onsubmit_text .= $text;
1316 }
a34b07a5 1317 }
1318
82dcbb1e 1319 if (!empty($onsubmit_text))
c8dc86c9 1320//FIXME: DON'T ECHO HTML FROM CORE!
82dcbb1e 1321 echo ' onsubmit="' . $onsubmit_text . ' return true;"';
a34b07a5 1322 }
5c4ff7bf 1323
a34b07a5 1324
c8dc86c9 1325//FIXME: NO HTML IN CORE!
48985d59 1326 echo ">\n";
1327
199a9ab8 1328//FIXME: DON'T ECHO HTML FROM CORE!
1329 echo addHidden('smtoken', sm_generate_security_token());
1330
c8dc86c9 1331//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1332 echo addHidden('startMessage', $startMessage);
4a1788b3 1333
41b94d65 1334 if ($action == 'draft') {
c8dc86c9 1335//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1336 echo addHidden('delete_draft', $passed_id);
48985d59 1337 }
1338 if (isset($delete_draft)) {
c8dc86c9 1339//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1340 echo addHidden('delete_draft', $delete_draft);
48985d59 1341 }
da95c4b6 1342 if (isset($session)) {
c8dc86c9 1343//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1344 echo addHidden('session', $session);
da95c4b6 1345 }
1c044820 1346
08bad2b1 1347 if (isset($passed_id)) {
c8dc86c9 1348//FIXME: DON'T ECHO HTML FROM CORE!
df96b37a 1349 echo addHidden('passed_id', $passed_id);
08bad2b1 1350 }
44560457 1351
e506b6e5 1352 if (isset($fwduid)) {
1353//FIXME: DON'T ECHO HTML FROM CORE!
1354 echo addHidden('fwduid', $fwduid);
1355 }
1356
9c3e6cd4 1357 if ($saved_draft == 'yes') {
774d79cc 1358 $oTemplate->assign('note', _("Your draft has been saved."));
762853f4 1359 $oTemplate->display('note.tpl');
9c3e6cd4 1360 }
1361 if ($mail_sent == 'yes') {
774d79cc 1362 $oTemplate->assign('note', _("Your mail has been sent."));
762853f4 1363 $oTemplate->display('note.tpl');
9c3e6cd4 1364 }
9c3e6cd4 1365 if ($compose_new_win == '1') {
762853f4 1366 $oTemplate->display('compose_newwin_close.tpl');
9c3e6cd4 1367 }
1638beb6 1368
78a35fcd 1369 if ($location_of_buttons == 'top') {
c8dc86c9 1370//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1371 showComposeButtonRow();
1372 }
48985d59 1373
762853f4 1374 $identities = array();
1e2a6ff6 1375 if (count($idents) > 1) {
762853f4 1376 reset($idents);
73ad81bf 1377 foreach($idents as $id => $data) {
762853f4 1378 $identities[$id] = $data['full_name'].' &lt;'.$data['email_address'].'&gt;';
73ad81bf 1379 }
762853f4 1380 }
1638beb6 1381
762853f4 1382 $oTemplate->assign('identities', $identities);
1383 $oTemplate->assign('identity_def', $identity);
1384 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1638beb6 1385
3047e291 1386 $oTemplate->assign('to', sm_encode_html_special_chars($send_to));
1387 $oTemplate->assign('cc', sm_encode_html_special_chars($send_to_cc));
1388 $oTemplate->assign('bcc', sm_encode_html_special_chars($send_to_bcc));
1389 $oTemplate->assign('subject', sm_encode_html_special_chars($subject));
1638beb6 1390
8949acd6 1391 // access keys...
1392 //
1393 global $accesskey_compose_to, $accesskey_compose_cc,
5f20677e 1394 $accesskey_compose_identity, $accesskey_compose_bcc,
1395 $accesskey_compose_subject;
1396 $oTemplate->assign('accesskey_compose_identity', $accesskey_compose_identity);
8949acd6 1397 $oTemplate->assign('accesskey_compose_to', $accesskey_compose_to);
1398 $oTemplate->assign('accesskey_compose_cc', $accesskey_compose_cc);
1399 $oTemplate->assign('accesskey_compose_bcc', $accesskey_compose_bcc);
1400 $oTemplate->assign('accesskey_compose_subject', $accesskey_compose_subject);
1401
762853f4 1402 $oTemplate->display('compose_header.tpl');
48985d59 1403
78a35fcd 1404 if ($location_of_buttons == 'between') {
c8dc86c9 1405//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1406 showComposeButtonRow();
1407 }
4dfb9db7 1408
762853f4 1409 $body_str = '';
48985d59 1410 if ($use_signature == true && $newmail == true && !isset($from_htmladdr_search)) {
1e2a6ff6 1411 $signature = $idents[$identity]['signature'];
d3c13a51 1412
3b17e952 1413 if ($sig_first == '1') {
50706f77 1414 /*
1415 * FIXME: test is specific to ja_JP translation implementation.
1416 * This test might apply incorrect conversion to other translations, but
91c27aee 1417 * use of 7bit iso-2022-jp charset in other translations might have other
50706f77 1418 * issues too.
1419 */
ab4700c3 1420 if ($default_charset == 'iso-2022-jp') {
762853f4 1421 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
83be314a 1422 } else {
762853f4 1423 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
83be314a 1424 }
3047e291 1425 $body_str .= "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
762853f4 1426 } else {
3047e291 1427 $body_str = "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
50706f77 1428 // FIXME: test is specific to ja_JP translation implementation. See above comments.
ab4700c3 1429 if ($default_charset == 'iso-2022-jp') {
762853f4 1430 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
1431 } else {
1432 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
73ad81bf 1433 }
3b17e952 1434 }
73ad81bf 1435 } else {
3047e291 1436 $body_str = sm_encode_html_special_chars(decodeHeader($body,false,false));
48985d59 1437 }
12a0ed01 1438
762853f4 1439 $oTemplate->assign('editor_width', (int)$editor_size);
1440 $oTemplate->assign('editor_height', (int)$editor_height);
1441 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1442 $oTemplate->assign('body', $body_str);
1443 $oTemplate->assign('show_bottom_send', $location_of_buttons!='bottom');
1638beb6 1444
8949acd6 1445 // access keys...
1446 //
1447 global $accesskey_compose_body, $accesskey_compose_send;
1448 $oTemplate->assign('accesskey_compose_body', $accesskey_compose_body);
1449 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1450
762853f4 1451 $oTemplate->display ('compose_body.tpl');
1638beb6 1452
48985d59 1453 if ($location_of_buttons == 'bottom') {
c8dc86c9 1454//FIXME: DON'T ECHO HTML FROM CORE!
48985d59 1455 showComposeButtonRow();
48985d59 1456 }
46bb8da8 1457
f8eb968d 1458 // composeMessage can be empty when coming from a restored session
1459 if (is_object($composeMessage) && $composeMessage->entities)
1460 $attach_array = $composeMessage->entities;
1461 if ($session_expired && !empty($attachments) && is_array($attachments))
1462 $attach_array = $attachments;
1463
48985d59 1464 /* This code is for attachments */
73ad81bf 1465 if ((bool) ini_get('file_uploads')) {
1466
1467 /* Calculate the max size for an uploaded file.
1468 * This is advisory for the user because we can't actually prevent
1469 * people to upload too large files. */
1470 $sizes = array();
1471 /* php.ini vars which influence the max for uploads */
1472 $configvars = array('post_max_size', 'memory_limit', 'upload_max_filesize');
1473 foreach($configvars as $var) {
4f21ba00 1474 /* skip 0 or empty values, and -1 which means 'unlimited' */
73ad81bf 1475 if( $size = getByteSize(ini_get($var)) ) {
4f21ba00 1476 if ( $size != '-1' ) {
1477 $sizes[] = $size;
1478 }
73ad81bf 1479 }
0a2c3218 1480 }
0a2c3218 1481
762853f4 1482 $attach = array();
1f270d3c 1483 global $username, $attachment_dir;
1484 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
f8eb968d 1485 if (!empty($attach_array)) {
1486 foreach ($attach_array as $key => $attachment) {
73ad81bf 1487 $attached_file = $attachment->att_local_name;
1488 if ($attachment->att_local_name || $attachment->body_part) {
1489 $attached_filename = decodeHeader($attachment->mime_header->getParameter('name'));
1490 $type = $attachment->mime_header->type0.'/'.
a91189d6 1491 $attachment->mime_header->type1;
1638beb6 1492
762853f4 1493 $a = array();
1494 $a['Key'] = $key;
1495 $a['FileName'] = $attached_filename;
1496 $a['ContentType'] = $type;
1f270d3c 1497 $a['Size'] = filesize($hashed_attachment_dir . '/' . $attached_file);
762853f4 1498 $attach[$key] = $a;
73ad81bf 1499 }
1500 }
4dfb9db7 1501 }
1638beb6 1502
762853f4 1503 $max = min($sizes);
1504 $oTemplate->assign('max_file_size', empty($max) ? -1 : $max);
1505 $oTemplate->assign('attachments', $attach);
1638beb6 1506
8949acd6 1507 // access keys...
1508 //
1509 global $accesskey_compose_attach_browse, $accesskey_compose_attach,
1510 $accesskey_compose_delete_attach;
1511 $oTemplate->assign('accesskey_compose_attach_browse', $accesskey_compose_attach_browse);
1512 $oTemplate->assign('accesskey_compose_attach', $accesskey_compose_attach);
1513 $oTemplate->assign('accesskey_compose_delete_attach', $accesskey_compose_delete_attach);
1514
762853f4 1515 $oTemplate->display('compose_attachments.tpl');
73ad81bf 1516 } // End of file_uploads if-block
41b94d65 1517 /* End of attachment code */
762853f4 1518
253ad942 1519 $oTemplate->assign('username', $username);
1520 $oTemplate->assign('smaction', $action);
1521 $oTemplate->assign('mailbox', $mailbox);
953fa718 1522 sqgetGlobalVar('QUERY_STRING', $queryString, SQ_SERVER);
253ad942 1523 $oTemplate->assign('querystring', $queryString);
1524 $oTemplate->assign('composesession', $composesession);
1525 $oTemplate->assign('send_button_count', unique_widget_name('send', TRUE));
1526 if (!empty($attach_array))
1527 $oTemplate->assign('attachments', urlencode(serialize($attach_array)));
1528
1529 $aUserNotices = array();
1530
1531 // File uploads are off, so we didn't show that part of the form.
1532 // To avoid bogus bug reports, tell the user why.
a64f47e7 1533 if (!(bool) ini_get('file_uploads')) {
253ad942 1534 $aUserNotices[] = _("Because PHP file uploads are turned off, you can not attach files to this message. Please see your system administrator for details.");
a64f47e7 1535 }
1536
253ad942 1537 $oTemplate->assign('user_notices', $aUserNotices);
1538
1539 $oTemplate->display('compose_form_close.tpl');
1540
762853f4 1541 if ($compose_new_win=='1') {
1542 $oTemplate->display('compose_newwin_close.tpl');
1543 }
1638beb6 1544
762853f4 1545 $oErrorHandler->setDelayedErrors(false);
5c4ff7bf 1546 $oTemplate->display('footer.tpl');
48985d59 1547}
1548
1549
70c4fd84 1550function showComposeButtonRow() {
78a35fcd 1551 global $use_javascript_addr_book, $save_as_draft,
73ad81bf 1552 $default_use_priority, $mailprio, $default_use_mdn,
1553 $request_mdn, $request_dr,
1554 $data_dir, $username;
70c4fd84 1555
762853f4 1556 global $oTemplate, $buffer_hook;
1638beb6 1557
1558 if ($default_use_priority) {
762853f4 1559 $priorities = array('1'=>_("High"), '3'=>_("Normal"), '5'=>_("Low"));
1560 $priority = isset($mailprio) ? $mailprio : 3;
1561 } else {
1562 $priorities = array();
1563 $priority = NULL;
ae25968c 1564 }
1638beb6 1565
ae25968c 1566 $mdn_user_support=getPref($data_dir, $username, 'mdn_user_support',$default_use_mdn);
48985d59 1567
8949acd6 1568 $address_book_button_attribs = array();
1569 global $accesskey_compose_addresses;
1570 if ($accesskey_compose_addresses != 'NONE')
1571 $address_book_button_attribs['accesskey'] = $accesskey_compose_addresses;
c40a269e 1572 if ($use_javascript_addr_book && checkForJavascript()) {
8949acd6 1573 $addr_book = addButton(_("Addresses"),
1574 null,
1575 array_merge($address_book_button_attribs, array('onclick' => 'javascript:open_abook();')));
734f4ee6 1576 } else {
8949acd6 1577 $addr_book = addSubmit(_("Addresses"), 'html_addr_search', $address_book_button_attribs);
78a35fcd 1578 }
48985d59 1579
762853f4 1580 $oTemplate->assign('allow_priority', $default_use_priority==1);
1581 $oTemplate->assign('priority_list', $priorities);
1582 $oTemplate->assign('current_priority', $priority);
1638beb6 1583
762853f4 1584 $oTemplate->assign('notifications_enabled', $mdn_user_support==1);
1585 $oTemplate->assign('read_receipt', $request_mdn=='1');
1586 $oTemplate->assign('delivery_receipt', $request_dr=='1');
1638beb6 1587
762853f4 1588 $oTemplate->assign('drafts_enabled', $save_as_draft);
1589 $oTemplate->assign('address_book_button', $addr_book);
441f2d33 1590
8949acd6 1591 // access keys...
1592 //
1593 global $accesskey_compose_priority, $accesskey_compose_on_read,
1594 $accesskey_compose_on_delivery, $accesskey_compose_signature,
1595 $accesskey_compose_save_draft, $accesskey_compose_send;
1596 $oTemplate->assign('accesskey_compose_priority', $accesskey_compose_priority);
1597 $oTemplate->assign('accesskey_compose_on_read', $accesskey_compose_on_read);
1598 $oTemplate->assign('accesskey_compose_on_delivery', $accesskey_compose_on_delivery);
1599 $oTemplate->assign('accesskey_compose_signature', $accesskey_compose_signature);
1600 $oTemplate->assign('accesskey_compose_save_draft', $accesskey_compose_save_draft);
1601 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1602
762853f4 1603 $oTemplate->display('compose_buttons.tpl');
78a35fcd 1604}
b278172f 1605
70c4fd84 1606function checkInput ($show) {
78a35fcd 1607 /*
1608 * I implemented the $show variable because the error messages
1609 * were getting sent before the page header. So, I check once
1610 * using $show=false, and then when i'm ready to display the error
1611 * message, show=true
1612 */
1356041d 1613 global $send_to, $send_to_cc, $send_to_bcc;
78a35fcd 1614
1356041d 1615 $send_to = trim($send_to);
1616 $send_to_cc = trim($send_to_cc);
1617 $send_to_bcc = trim($send_to_bcc);
1618 if (empty($send_to) && empty($send_to_cc) && empty($send_to_bcc)) {
78a35fcd 1619 if ($show) {
cb34dbd0 1620 plain_error_message(_("You have not filled in the \"To:\" field."));
78a35fcd 1621 }
1622 return false;
1623 }
1624 return true;
1625} /* function checkInput() */
df15de21 1626
3806fa52 1627
00793a25 1628/* True if FAILURE */
da95c4b6 1629function saveAttachedFiles($session) {
b4e7df34 1630 global $composeMessage, $username, $attachment_dir;
bfa54da7 1631
45cdd1b5 1632 /* get out of here if no file was attached at all */
1633 if (! is_uploaded_file($_FILES['attachfile']['tmp_name']) ) {
1634 return true;
1635 }
1636
1f270d3c 1637 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1638 $localfilename = sq_get_attach_tempfile();
1f270d3c 1639 $fullpath = $hashed_attachment_dir . '/' . $localfilename;
4c9d2242 1640
a42c236f 1641 // m_u_f works better with restricted PHP installs (safe_mode, open_basedir),
1642 // if that doesn't work, try a simple rename.
8442ecb9 1643 if (!sq_call_function_suppress_errors('move_uploaded_file', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
1644 if (!sq_call_function_suppress_errors('rename', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
73ad81bf 1645 return true;
1646 }
a61878d0 1647 }
0b97a708 1648 $type = strtolower($_FILES['attachfile']['type']);
1649 $name = $_FILES['attachfile']['name'];
b4e7df34 1650 $composeMessage->initAttachment($type, $name, $localfilename);
4c9d2242 1651}
1652
5fe7d683 1653/**
1654 * Parse strings such as "8M" and "2k" into their corresponding size in bytes
1655 *
1656 * NOTE: This function only recognizes the suffixes "K", "M" and "G"
1657 * and will probably break very easily if the given size is in
1658 * some completely different format.
1659 *
1660 * @param string $ini_size The input string to be converted
1661 *
1662 * @return mixed Boolean FALSE if something went wrong (the value passed in
1663 * was empty?, the suffix was not recognized?), otherwise, the
1664 * converted size in bytes (just the number (as an integer),
1665 * no unit identifier included)
1666 *
1667 */
0a2c3218 1668function getByteSize($ini_size) {
1669
4d30dc83 1670 if(!$ini_size) {
1671 return FALSE;
1672 }
da95c4b6 1673
0a2c3218 1674 $ini_size = trim($ini_size);
1675
5b9716de 1676 // if there's some kind of letter at the end of the string we need to multiply.
1677 if(!is_numeric(substr($ini_size, -1))) {
1678
1679 switch(strtoupper(substr($ini_size, -1))) {
1680 case 'G':
73ad81bf 1681 $bytesize = 1073741824;
1682 break;
5b9716de 1683 case 'M':
73ad81bf 1684 $bytesize = 1048576;
1685 break;
5b9716de 1686 case 'K':
73ad81bf 1687 $bytesize = 1024;
1688 break;
5fe7d683 1689 default:
1690 return FALSE;
5b9716de 1691 }
1692
4d30dc83 1693 return ($bytesize * (int)substr($ini_size, 0, -1));
0a2c3218 1694 }
1c044820 1695
4d30dc83 1696 return $ini_size;
0a2c3218 1697}
a43e4b90 1698
4c9d2242 1699
50706f77 1700/**
1701 * temporary function to make use of the deliver class.
a42c236f 1702 * In the future the responsible backend should be automaticly loaded
50706f77 1703 * and conf.pl should show a list of available backends.
1704 * The message also should be constructed by the message class.
b67d61ee 1705 *
10adeb76 1706 * @param object $composeMessage The message being sent. Please note
1707 * that it is passed by reference and
1708 * will be returned modified, with additional
1709 * headers, such as Message-ID, Date, In-Reply-To,
1710 * References, and so forth.
1711 *
b67d61ee 1712 * @return boolean FALSE if delivery failed, or some non-FALSE value
1713 * upon success.
1714 *
73ad81bf 1715 */
10adeb76 1716function deliverMessage(&$composeMessage, $draft=false) {
a43e4b90 1717 global $send_to, $send_to_cc, $send_to_bcc, $mailprio, $subject, $body,
7b2092f1 1718 $username, $identity, $idents, $data_dir, $compose_messages, $session,
856e58ef 1719 $request_mdn, $request_dr, $default_charset, $useSendmail,
1720 $domain, $action, $default_move_to_sent, $move_to_sent,
a9805897 1721 $imapServerAddress, $imapPort, $imap_stream_options, $sent_folder, $key;
a43e4b90 1722
1723 $rfc822_header = $composeMessage->rfc822_header;
24192f77 1724
1725 $abook = addressbook_init(false, true);
310dfeb6 1726 $rfc822_header->to = $rfc822_header->parseAddress($send_to,true, array(), '', $domain, array(&$abook,'lookup'));
1727 $rfc822_header->cc = $rfc822_header->parseAddress($send_to_cc,true,array(), '',$domain, array(&$abook,'lookup'));
1728 $rfc822_header->bcc = $rfc822_header->parseAddress($send_to_bcc,true, array(), '',$domain, array(&$abook,'lookup'));
a43e4b90 1729 $rfc822_header->priority = $mailprio;
1730 $rfc822_header->subject = $subject;
310dfeb6 1731
a43e4b90 1732 $special_encoding='';
1733 if (strtolower($default_charset) == 'iso-2022-jp') {
1734 if (mb_detect_encoding($body) == 'ASCII') {
a91189d6 1735 $special_encoding = '8bit';
a43e4b90 1736 } else {
1737 $body = mb_convert_encoding($body, 'JIS');
1738 $special_encoding = '7bit';
1739 }
1740 }
1741 $composeMessage->setBody($body);
1742
a43e4b90 1743 $reply_to = '';
1e2a6ff6 1744 $reply_to = $idents[$identity]['reply_to'];
52ead32b 1745 if ($reply_to && strpos($reply_to, '@') === FALSE)
8b213268 1746 $reply_to .= '@' . $domain;
40e07136 1747
1748 $from_addr = build_from_header($identity);
1749 $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
a43e4b90 1750 if ($reply_to) {
73ad81bf 1751 $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
a43e4b90 1752 }
1753 /* Receipt: On Read */
1754 if (isset($request_mdn) && $request_mdn) {
40e07136 1755 $rfc822_header->dnt = $rfc822_header->parseAddress($from_addr,true);
762853f4 1756 } elseif (isset($rfc822_header->dnt)) {
1757 unset($rfc822_header->dnt);
a43e4b90 1758 }
1638beb6 1759
a43e4b90 1760 /* Receipt: On Delivery */
657fe1bd 1761 if (!empty($request_dr)) {
1762//FIXME: it would be better to fiddle with headers inside of the message object or possibly when delivering the message to its destination; is this possible?
cc51047f 1763 $rfc822_header->more_headers['Return-Receipt-To'] = $from_addr;
762853f4 1764 } elseif (isset($rfc822_header->more_headers['Return-Receipt-To'])) {
1765 unset($rfc822_header->more_headers['Return-Receipt-To']);
a43e4b90 1766 }
762853f4 1767
a43e4b90 1768 /* multipart messages */
1769 if (count($composeMessage->entities)) {
1770 $message_body = new Message();
a91189d6 1771 $message_body->body_part = $composeMessage->body_part;
1772 $composeMessage->body_part = '';
1773 $mime_header = new MessageHeader;
1774 $mime_header->type0 = 'text';
1775 $mime_header->type1 = 'plain';
1776 if ($special_encoding) {
1777 $mime_header->encoding = $special_encoding;
1c044820 1778 } else {
12a0ed01 1779 $mime_header->encoding = '8bit';
a91189d6 1780 }
1781 if ($default_charset) {
1782 $mime_header->parameters['charset'] = $default_charset;
1783 }
1c044820 1784 $message_body->mime_header = $mime_header;
a43e4b90 1785 array_unshift($composeMessage->entities, $message_body);
a91189d6 1786 $content_type = new ContentType('multipart/mixed');
a43e4b90 1787 } else {
1e2026df 1788 $content_type = new ContentType('text/plain');
1789 if ($special_encoding) {
1790 $rfc822_header->encoding = $special_encoding;
1c044820 1791 } else {
1e2026df 1792 $rfc822_header->encoding = '8bit';
1c044820 1793 }
426e0b72 1794 if ($default_charset) {
1795 $content_type->properties['charset']=$default_charset;
73ad81bf 1796 }
181538ac 1797 }
1c044820 1798
a43e4b90 1799 $rfc822_header->content_type = $content_type;
1800 $composeMessage->rfc822_header = $rfc822_header;
0fdb0aa1 1801 if ($action == 'reply' || $action == 'reply_all') {
1802 global $passed_id, $passed_ent_id;
1803 $reply_id = $passed_id;
1804 $reply_ent_id = $passed_ent_id;
1805 } else {
1806 $reply_id = '';
1807 $reply_ent_id = '';
1808 }
1638beb6 1809
1c044820 1810 /* Here you can modify the message structure just before we hand
6e515418 1811 it over to deliver; plugin authors note that $composeMessage
1812 is sent and modified by reference since 1.5.2 */
1813 do_hook('compose_send', $composeMessage);
66540988 1814//TODO: need to migrate to the following, but it neessitates changes in existing plugins, since the args are now an array
1815 //$temp = array(&$composeMessage, &$draft);
1816 //do_hook('compose_send', $temp);
a43e4b90 1817
aff28a6d 1818 // remove special header if present and prepare to mark
1819 // a message that a draft was composed in reply to
1820 if (!empty($composeMessage->rfc822_header->x_sm_flag_reply) && !$draft) {
1821 global $passed_id, $mailbox;
1822 // tricks the code below that marks the reply
1823 list($action, $passed_id, $mailbox) = explode('::', $rfc822_header->x_sm_flag_reply, 3);
1824 unset($composeMessage->rfc822_header->x_sm_flag_reply);
1825 unset($composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply']);
1826 }
1827
b48d3c53 1828 if (!$useSendmail && !$draft) {
a91189d6 1829 require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
1830 $deliver = new Deliver_SMTP();
a9805897 1831 global $smtpServerAddress, $smtpPort, $smtp_stream_options, $pop_before_smtp, $pop_before_smtp_host;
a91189d6 1832
a91189d6 1833 $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
783e926e 1834 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
9bd3b1e6 1835 get_smtp_user($user, $pass);
a91189d6 1836 $stream = $deliver->initStream($composeMessage,$domain,0,
a9805897 1837 $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host, $smtp_stream_options);
b48d3c53 1838 } elseif (!$draft) {
73ad81bf 1839 require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
fd7ab795 1840 global $sendmail_path, $sendmail_args;
f3dc9c62 1841 // Check for outdated configuration
1842 if (!isset($sendmail_args)) {
1843 if ($sendmail_path=='/var/qmail/bin/qmail-inject') {
1844 $sendmail_args = '';
1845 } else {
1846 $sendmail_args = '-i -t';
1847 }
1848 }
fd7ab795 1849 $deliver = new Deliver_SendMail(array('sendmail_args'=>$sendmail_args));
73ad81bf 1850 $stream = $deliver->initStream($composeMessage,$sendmail_path);
b48d3c53 1851 } elseif ($draft) {
73ad81bf 1852 global $draft_folder;
906f7e9f 1853 $imap_stream = sqimap_login($username, false, $imapServerAddress,
a9805897 1854 $imapPort, 0, $imap_stream_options);
73ad81bf 1855 if (sqimap_mailbox_exists ($imap_stream, $draft_folder)) {
aff28a6d 1856//TODO: this can leak private information about folders and message IDs if messages are accessed/sent from another client --- should this feature be optional?
1857 // make note of the message to mark as having been replied to
1858 global $passed_id, $mailbox;
1859 if ($action == 'reply' || $action == 'reply_all' || $action == 'forward' || $action == 'forward_as_attachment') {
1860 $composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply'] = $action . '::' . $passed_id . '::' . $mailbox;
1861 }
1862
73ad81bf 1863 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1864 $imap_deliver = new Deliver_IMAP();
a90d951c 1865 $success = $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $draft_folder);
73ad81bf 1866 sqimap_logout($imap_stream);
1867 unset ($imap_deliver);
c077ffeb 1868 $composeMessage->purgeAttachments();
7b2092f1 1869//TODO: completely unclear if should be using $compose_session instead of $session below
1870 unset($compose_messages[$session]);
1871 sqsession_register($compose_messages,'compose_messages');
b67d61ee 1872 return $success;
4dfb9db7 1873 } else {
3047e291 1874 $msg = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), sm_encode_html_special_chars($draft_folder));
cb34dbd0 1875 plain_error_message($msg);
73ad81bf 1876 return false;
a91189d6 1877 }
a43e4b90 1878 }
0c59bbe1 1879 $success = false;
a43e4b90 1880 if ($stream) {
10adeb76 1881 $deliver->mail($composeMessage, $stream, $reply_id, $reply_ent_id);
0c59bbe1 1882 $success = $deliver->finalizeStream($stream);
a43e4b90 1883 }
0c59bbe1 1884 if (!$success) {
fd7ab795 1885 // $deliver->dlv_server_msg is not always server's reply
32433689 1886 $msg = _("Message not sent.")
1887 . "<br />\n"
1888 . (isset($deliver->dlv_msg) ? $deliver->dlv_msg : '');
a15f9d93 1889 if (!empty($deliver->dlv_server_msg)) {
1890 // add 'server replied' part only when it is not empty.
1891 // Delivery error can be generated by delivery class itself
32433689 1892 $msg .= '<br />'
1893 . _("Server replied:") . ' '
1894 . (isset($deliver->dlv_ret_nr) ? $deliver->dlv_ret_nr . ' ' : '')
3047e291 1895 . nl2br(sm_encode_html_special_chars($deliver->dlv_server_msg));
a15f9d93 1896 }
cb34dbd0 1897 plain_error_message($msg);
a43e4b90 1898 } else {
1899 unset ($deliver);
a9805897 1900 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, 0, $imap_stream_options);
e4a1f097 1901
8780308f 1902
414303b8 1903 // mark as replied or forwarded if applicable
1904 //
e506b6e5 1905 global $what, $iAccount, $startMessage, $passed_id, $fwduid, $mailbox;
8780308f 1906
bc29bf70 1907 if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
202bcbcc 1908 require(SM_PATH . 'functions/mailbox_display.php');
aff28a6d 1909 // select errors here could be due to a draft reply being sent
1910 // after the original message's mailbox is moved or deleted
1911 $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array(), false);
1912 // a non-empty return from above means we can proceed
1913 if (!empty($aMailbox)) {
1914 switch($action) {
1915 case 'reply':
1916 case 'reply_all':
1917 // check if we are allowed to set the \\Answered flag
1918 if (in_array('\\answered',$aMailbox['PERMANENTFLAGS'], true)) {
1919 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
1920 if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
1921 /**
1922 * Only update the cached headers if the header is
1923 * cached.
1924 */
1925 if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
1926 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
1927 }
bc29bf70 1928 }
1929 }
aff28a6d 1930 break;
1931 case 'forward':
1932 case 'forward_as_attachment':
1933 // check if we are allowed to set the $Forwarded flag (RFC 4550 paragraph 2.8)
1934 if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
1935 in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
1936
1937 // when forwarding as an attachment from the message
1938 // list, passed_id is not used, need to get UID(s)
1939 // from the query string
1940 //
1941 if (empty($passed_id) && !empty($fwduid))
1942 $ids = explode('_', $fwduid);
1943 else
1944 $ids = array($passed_id);
e506b6e5 1945
aff28a6d 1946 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, $ids, '$Forwarded', true, false);
e506b6e5 1947
aff28a6d 1948 foreach ($ids as $id) {
1949 if (isset($aUpdatedMsgs[$id]['FLAGS'])) {
1950 if (isset($aMailbox['MSG_HEADERS'][$id])) {
1951 $aMailbox['MSG_HEADERS'][$id]['FLAGS'] = $aMsg['FLAGS'];
1952 }
e506b6e5 1953 }
bc29bf70 1954 }
bda07b93 1955 }
aff28a6d 1956 break;
8780308f 1957 }
bc29bf70 1958
aff28a6d 1959 /**
1960 * Write mailbox with updated seen flag information back to cache.
1961 */
1962 if(isset($aUpdatedMsgs[$passed_id])) {
1963 $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
1964 sqsession_register($mailbox_cache,'mailbox_cache');
1965 }
bc29bf70 1966 }
a91189d6 1967 }
414303b8 1968
1969
1970 // move to sent folder
1971 //
1972 $move_to_sent = getPref($data_dir,$username,'move_to_sent');
1973 if (isset($default_move_to_sent) && ($default_move_to_sent != 0)) {
1974 $svr_allow_sent = true;
1975 } else {
1976 $svr_allow_sent = false;
1977 }
1978
1979 if (isset($sent_folder) && (($sent_folder != '') || ($sent_folder != 'none'))
1980 && sqimap_mailbox_exists( $imap_stream, $sent_folder)) {
1981 $fld_sent = true;
1982 } else {
1983 $fld_sent = false;
1984 }
1985
1986 if ((isset($move_to_sent) && ($move_to_sent != 0)) || (!isset($move_to_sent))) {
1987 $lcl_allow_sent = true;
1988 } else {
1989 $lcl_allow_sent = false;
1990 }
1991
1992 if (($fld_sent && $svr_allow_sent && !$lcl_allow_sent) || ($fld_sent && $lcl_allow_sent)) {
1993 if ($action == 'reply' || $action == 'reply_all') {
1994 $save_reply_with_orig=getPref($data_dir,$username,'save_reply_with_orig');
1995 if ($save_reply_with_orig) {
1996 $sent_folder = $mailbox;
1997 }
1998 }
414303b8 1999 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
2000 $imap_deliver = new Deliver_IMAP();
33f0da43 2001 $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $sent_folder);
414303b8 2002 unset ($imap_deliver);
2003 }
2004
2005
2006 // final cleanup
2007 //
2008 $composeMessage->purgeAttachments();
7b2092f1 2009//TODO: completely unclear if should be using $compose_session instead of $session below
2010 unset($compose_messages[$session]);
2011 sqsession_register($compose_messages,'compose_messages');
414303b8 2012 sqimap_logout($imap_stream);
2013
a43e4b90 2014 }
0c59bbe1 2015 return $success;
a43e4b90 2016}