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