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