Add accesskeys accessibility implementation. Need to keep adding other pages, especi...
[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,
1222 $accesskey_compose_bcc, $accesskey_compose_subject;
1223 $oTemplate->assign('accesskey_compose_to', $accesskey_compose_to);
1224 $oTemplate->assign('accesskey_compose_cc', $accesskey_compose_cc);
1225 $oTemplate->assign('accesskey_compose_bcc', $accesskey_compose_bcc);
1226 $oTemplate->assign('accesskey_compose_subject', $accesskey_compose_subject);
1227
762853f4 1228 $oTemplate->display('compose_header.tpl');
48985d59 1229
78a35fcd 1230 if ($location_of_buttons == 'between') {
c8dc86c9 1231//FIXME: DON'T ECHO HTML FROM CORE!
78a35fcd 1232 showComposeButtonRow();
1233 }
4dfb9db7 1234
762853f4 1235 $body_str = '';
48985d59 1236 if ($use_signature == true && $newmail == true && !isset($from_htmladdr_search)) {
1e2a6ff6 1237 $signature = $idents[$identity]['signature'];
d3c13a51 1238
3b17e952 1239 if ($sig_first == '1') {
50706f77 1240 /*
1241 * FIXME: test is specific to ja_JP translation implementation.
1242 * This test might apply incorrect conversion to other translations, but
91c27aee 1243 * use of 7bit iso-2022-jp charset in other translations might have other
50706f77 1244 * issues too.
1245 */
ab4700c3 1246 if ($default_charset == 'iso-2022-jp') {
762853f4 1247 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
83be314a 1248 } else {
762853f4 1249 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
83be314a 1250 }
762853f4 1251 $body_str .= "\n\n".htmlspecialchars(decodeHeader($body,false,false));
1252 } else {
1253 $body_str = "\n\n".htmlspecialchars(decodeHeader($body,false,false));
50706f77 1254 // FIXME: test is specific to ja_JP translation implementation. See above comments.
ab4700c3 1255 if ($default_charset == 'iso-2022-jp') {
762853f4 1256 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
1257 } else {
1258 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
73ad81bf 1259 }
3b17e952 1260 }
73ad81bf 1261 } else {
762853f4 1262 $body_str = htmlspecialchars(decodeHeader($body,false,false));
48985d59 1263 }
12a0ed01 1264
762853f4 1265 $oTemplate->assign('editor_width', (int)$editor_size);
1266 $oTemplate->assign('editor_height', (int)$editor_height);
1267 $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
1268 $oTemplate->assign('body', $body_str);
1269 $oTemplate->assign('show_bottom_send', $location_of_buttons!='bottom');
1638beb6 1270
8949acd6 1271 // access keys...
1272 //
1273 global $accesskey_compose_body, $accesskey_compose_send;
1274 $oTemplate->assign('accesskey_compose_body', $accesskey_compose_body);
1275 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1276
762853f4 1277 $oTemplate->display ('compose_body.tpl');
1638beb6 1278
48985d59 1279 if ($location_of_buttons == 'bottom') {
c8dc86c9 1280//FIXME: DON'T ECHO HTML FROM CORE!
48985d59 1281 showComposeButtonRow();
48985d59 1282 }
46bb8da8 1283
f8eb968d 1284 // composeMessage can be empty when coming from a restored session
1285 if (is_object($composeMessage) && $composeMessage->entities)
1286 $attach_array = $composeMessage->entities;
1287 if ($session_expired && !empty($attachments) && is_array($attachments))
1288 $attach_array = $attachments;
1289
48985d59 1290 /* This code is for attachments */
73ad81bf 1291 if ((bool) ini_get('file_uploads')) {
1292
1293 /* Calculate the max size for an uploaded file.
1294 * This is advisory for the user because we can't actually prevent
1295 * people to upload too large files. */
1296 $sizes = array();
1297 /* php.ini vars which influence the max for uploads */
1298 $configvars = array('post_max_size', 'memory_limit', 'upload_max_filesize');
1299 foreach($configvars as $var) {
4f21ba00 1300 /* skip 0 or empty values, and -1 which means 'unlimited' */
73ad81bf 1301 if( $size = getByteSize(ini_get($var)) ) {
4f21ba00 1302 if ( $size != '-1' ) {
1303 $sizes[] = $size;
1304 }
73ad81bf 1305 }
0a2c3218 1306 }
0a2c3218 1307
762853f4 1308 $attach = array();
1f270d3c 1309 global $username, $attachment_dir;
1310 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
f8eb968d 1311 if (!empty($attach_array)) {
1312 foreach ($attach_array as $key => $attachment) {
73ad81bf 1313 $attached_file = $attachment->att_local_name;
1314 if ($attachment->att_local_name || $attachment->body_part) {
1315 $attached_filename = decodeHeader($attachment->mime_header->getParameter('name'));
1316 $type = $attachment->mime_header->type0.'/'.
a91189d6 1317 $attachment->mime_header->type1;
1638beb6 1318
762853f4 1319 $a = array();
1320 $a['Key'] = $key;
1321 $a['FileName'] = $attached_filename;
1322 $a['ContentType'] = $type;
1f270d3c 1323 $a['Size'] = filesize($hashed_attachment_dir . '/' . $attached_file);
762853f4 1324 $attach[$key] = $a;
73ad81bf 1325 }
1326 }
4dfb9db7 1327 }
1638beb6 1328
762853f4 1329 $max = min($sizes);
1330 $oTemplate->assign('max_file_size', empty($max) ? -1 : $max);
1331 $oTemplate->assign('attachments', $attach);
1638beb6 1332
8949acd6 1333 // access keys...
1334 //
1335 global $accesskey_compose_attach_browse, $accesskey_compose_attach,
1336 $accesskey_compose_delete_attach;
1337 $oTemplate->assign('accesskey_compose_attach_browse', $accesskey_compose_attach_browse);
1338 $oTemplate->assign('accesskey_compose_attach', $accesskey_compose_attach);
1339 $oTemplate->assign('accesskey_compose_delete_attach', $accesskey_compose_delete_attach);
1340
762853f4 1341 $oTemplate->display('compose_attachments.tpl');
73ad81bf 1342 } // End of file_uploads if-block
41b94d65 1343 /* End of attachment code */
762853f4 1344
60445d64 1345//FIXME: no direct echoing to browser, no HTML output in core!
762853f4 1346 echo addHidden('username', $username).
1347 addHidden('smaction', $action).
1348 addHidden('mailbox', $mailbox);
953fa718 1349 sqgetGlobalVar('QUERY_STRING', $queryString, SQ_SERVER);
60445d64 1350//FIXME: no direct echoing to browser, no HTML output in core!
f8eb968d 1351 echo addHidden('composesession', $composesession).
73ad81bf 1352 addHidden('querystring', $queryString).
f8eb968d 1353 (!empty($attach_array) ?
1354 addHidden('attachments', urlencode(serialize($attach_array))) : '').
73ad81bf 1355 "</form>\n";
a64f47e7 1356 if (!(bool) ini_get('file_uploads')) {
73ad81bf 1357 /* File uploads are off, so we didn't show that part of the form.
1358 To avoid bogus bug reports, tell the user why. */
60445d64 1359//FIXME: no direct echoing to browser, no HTML output in core!
50706f77 1360 echo '<p style="text-align:center">'
1361 . _("Because PHP file uploads are turned off, you can not attach files to this message. Please see your system administrator for details.")
1362 . "</p>\r\n";
a64f47e7 1363 }
1364
762853f4 1365 if ($compose_new_win=='1') {
1366 $oTemplate->display('compose_newwin_close.tpl');
1367 }
1638beb6 1368
d22879f7 1369 do_hook('compose_bottom', $null);
1370
762853f4 1371 $oErrorHandler->setDelayedErrors(false);
5c4ff7bf 1372 $oTemplate->display('footer.tpl');
48985d59 1373}
1374
1375
70c4fd84 1376function showComposeButtonRow() {
78a35fcd 1377 global $use_javascript_addr_book, $save_as_draft,
73ad81bf 1378 $default_use_priority, $mailprio, $default_use_mdn,
1379 $request_mdn, $request_dr,
1380 $data_dir, $username;
70c4fd84 1381
762853f4 1382 global $oTemplate, $buffer_hook;
1638beb6 1383
1384 if ($default_use_priority) {
762853f4 1385 $priorities = array('1'=>_("High"), '3'=>_("Normal"), '5'=>_("Low"));
1386 $priority = isset($mailprio) ? $mailprio : 3;
1387 } else {
1388 $priorities = array();
1389 $priority = NULL;
ae25968c 1390 }
1638beb6 1391
ae25968c 1392 $mdn_user_support=getPref($data_dir, $username, 'mdn_user_support',$default_use_mdn);
48985d59 1393
8949acd6 1394 $address_book_button_attribs = array();
1395 global $accesskey_compose_addresses;
1396 if ($accesskey_compose_addresses != 'NONE')
1397 $address_book_button_attribs['accesskey'] = $accesskey_compose_addresses;
c40a269e 1398 if ($use_javascript_addr_book && checkForJavascript()) {
8949acd6 1399 $addr_book = addButton(_("Addresses"),
1400 null,
1401 array_merge($address_book_button_attribs, array('onclick' => 'javascript:open_abook();')));
734f4ee6 1402 } else {
8949acd6 1403 $addr_book = addSubmit(_("Addresses"), 'html_addr_search', $address_book_button_attribs);
78a35fcd 1404 }
48985d59 1405
762853f4 1406 $oTemplate->assign('allow_priority', $default_use_priority==1);
1407 $oTemplate->assign('priority_list', $priorities);
1408 $oTemplate->assign('current_priority', $priority);
1638beb6 1409
762853f4 1410 $oTemplate->assign('notifications_enabled', $mdn_user_support==1);
1411 $oTemplate->assign('read_receipt', $request_mdn=='1');
1412 $oTemplate->assign('delivery_receipt', $request_dr=='1');
1638beb6 1413
762853f4 1414 $oTemplate->assign('drafts_enabled', $save_as_draft);
1415 $oTemplate->assign('address_book_button', $addr_book);
441f2d33 1416
8949acd6 1417 // access keys...
1418 //
1419 global $accesskey_compose_priority, $accesskey_compose_on_read,
1420 $accesskey_compose_on_delivery, $accesskey_compose_signature,
1421 $accesskey_compose_save_draft, $accesskey_compose_send;
1422 $oTemplate->assign('accesskey_compose_priority', $accesskey_compose_priority);
1423 $oTemplate->assign('accesskey_compose_on_read', $accesskey_compose_on_read);
1424 $oTemplate->assign('accesskey_compose_on_delivery', $accesskey_compose_on_delivery);
1425 $oTemplate->assign('accesskey_compose_signature', $accesskey_compose_signature);
1426 $oTemplate->assign('accesskey_compose_save_draft', $accesskey_compose_save_draft);
1427 $oTemplate->assign('accesskey_compose_send', $accesskey_compose_send);
1428
762853f4 1429 $oTemplate->display('compose_buttons.tpl');
78a35fcd 1430}
b278172f 1431
70c4fd84 1432function checkInput ($show) {
78a35fcd 1433 /*
1434 * I implemented the $show variable because the error messages
1435 * were getting sent before the page header. So, I check once
1436 * using $show=false, and then when i'm ready to display the error
1437 * message, show=true
1438 */
1356041d 1439 global $send_to, $send_to_cc, $send_to_bcc;
78a35fcd 1440
1356041d 1441 $send_to = trim($send_to);
1442 $send_to_cc = trim($send_to_cc);
1443 $send_to_bcc = trim($send_to_bcc);
1444 if (empty($send_to) && empty($send_to_cc) && empty($send_to_bcc)) {
78a35fcd 1445 if ($show) {
cb34dbd0 1446 plain_error_message(_("You have not filled in the \"To:\" field."));
78a35fcd 1447 }
1448 return false;
1449 }
1450 return true;
1451} /* function checkInput() */
df15de21 1452
3806fa52 1453
00793a25 1454/* True if FAILURE */
da95c4b6 1455function saveAttachedFiles($session) {
b4e7df34 1456 global $composeMessage, $username, $attachment_dir;
bfa54da7 1457
45cdd1b5 1458 /* get out of here if no file was attached at all */
1459 if (! is_uploaded_file($_FILES['attachfile']['tmp_name']) ) {
1460 return true;
1461 }
1462
1f270d3c 1463 $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
628bce99 1464 $localfilename = sq_get_attach_tempfile();
1f270d3c 1465 $fullpath = $hashed_attachment_dir . '/' . $localfilename;
4c9d2242 1466
a42c236f 1467 // m_u_f works better with restricted PHP installs (safe_mode, open_basedir),
1468 // if that doesn't work, try a simple rename.
8442ecb9 1469 if (!sq_call_function_suppress_errors('move_uploaded_file', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
1470 if (!sq_call_function_suppress_errors('rename', array($_FILES['attachfile']['tmp_name'], $fullpath))) {
73ad81bf 1471 return true;
1472 }
a61878d0 1473 }
0b97a708 1474 $type = strtolower($_FILES['attachfile']['type']);
1475 $name = $_FILES['attachfile']['name'];
b4e7df34 1476 $composeMessage->initAttachment($type, $name, $localfilename);
4c9d2242 1477}
1478
0a2c3218 1479/* parse values like 8M and 2k into bytes */
1480function getByteSize($ini_size) {
1481
4d30dc83 1482 if(!$ini_size) {
1483 return FALSE;
1484 }
da95c4b6 1485
0a2c3218 1486 $ini_size = trim($ini_size);
1487
5b9716de 1488 // if there's some kind of letter at the end of the string we need to multiply.
1489 if(!is_numeric(substr($ini_size, -1))) {
1490
1491 switch(strtoupper(substr($ini_size, -1))) {
1492 case 'G':
73ad81bf 1493 $bytesize = 1073741824;
1494 break;
5b9716de 1495 case 'M':
73ad81bf 1496 $bytesize = 1048576;
1497 break;
5b9716de 1498 case 'K':
73ad81bf 1499 $bytesize = 1024;
1500 break;
5b9716de 1501 }
1502
4d30dc83 1503 return ($bytesize * (int)substr($ini_size, 0, -1));
0a2c3218 1504 }
1c044820 1505
4d30dc83 1506 return $ini_size;
0a2c3218 1507}
a43e4b90 1508
4c9d2242 1509
50706f77 1510/**
1511 * temporary function to make use of the deliver class.
a42c236f 1512 * In the future the responsible backend should be automaticly loaded
50706f77 1513 * and conf.pl should show a list of available backends.
1514 * The message also should be constructed by the message class.
b67d61ee 1515 *
10adeb76 1516 * @param object $composeMessage The message being sent. Please note
1517 * that it is passed by reference and
1518 * will be returned modified, with additional
1519 * headers, such as Message-ID, Date, In-Reply-To,
1520 * References, and so forth.
1521 *
b67d61ee 1522 * @return boolean FALSE if delivery failed, or some non-FALSE value
1523 * upon success.
1524 *
73ad81bf 1525 */
10adeb76 1526function deliverMessage(&$composeMessage, $draft=false) {
a43e4b90 1527 global $send_to, $send_to_cc, $send_to_bcc, $mailprio, $subject, $body,
10adeb76 1528 $username, $identity, $idents, $data_dir,
856e58ef 1529 $request_mdn, $request_dr, $default_charset, $useSendmail,
1530 $domain, $action, $default_move_to_sent, $move_to_sent,
1531 $imapServerAddress, $imapPort, $sent_folder, $key;
a43e4b90 1532
1533 $rfc822_header = $composeMessage->rfc822_header;
24192f77 1534
1535 $abook = addressbook_init(false, true);
310dfeb6 1536 $rfc822_header->to = $rfc822_header->parseAddress($send_to,true, array(), '', $domain, array(&$abook,'lookup'));
1537 $rfc822_header->cc = $rfc822_header->parseAddress($send_to_cc,true,array(), '',$domain, array(&$abook,'lookup'));
1538 $rfc822_header->bcc = $rfc822_header->parseAddress($send_to_bcc,true, array(), '',$domain, array(&$abook,'lookup'));
a43e4b90 1539 $rfc822_header->priority = $mailprio;
1540 $rfc822_header->subject = $subject;
310dfeb6 1541
a43e4b90 1542 $special_encoding='';
1543 if (strtolower($default_charset) == 'iso-2022-jp') {
1544 if (mb_detect_encoding($body) == 'ASCII') {
a91189d6 1545 $special_encoding = '8bit';
a43e4b90 1546 } else {
1547 $body = mb_convert_encoding($body, 'JIS');
1548 $special_encoding = '7bit';
1549 }
1550 }
1551 $composeMessage->setBody($body);
1552
a43e4b90 1553 $reply_to = '';
1e2a6ff6 1554 $reply_to = $idents[$identity]['reply_to'];
40e07136 1555
1556 $from_addr = build_from_header($identity);
1557 $rfc822_header->from = $rfc822_header->parseAddress($from_addr,true);
a43e4b90 1558 if ($reply_to) {
73ad81bf 1559 $rfc822_header->reply_to = $rfc822_header->parseAddress($reply_to,true);
a43e4b90 1560 }
1561 /* Receipt: On Read */
1562 if (isset($request_mdn) && $request_mdn) {
40e07136 1563 $rfc822_header->dnt = $rfc822_header->parseAddress($from_addr,true);
762853f4 1564 } elseif (isset($rfc822_header->dnt)) {
1565 unset($rfc822_header->dnt);
a43e4b90 1566 }
1638beb6 1567
a43e4b90 1568 /* Receipt: On Delivery */
657fe1bd 1569 if (!empty($request_dr)) {
1570//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 1571 $rfc822_header->more_headers['Return-Receipt-To'] = $from_addr;
762853f4 1572 } elseif (isset($rfc822_header->more_headers['Return-Receipt-To'])) {
1573 unset($rfc822_header->more_headers['Return-Receipt-To']);
a43e4b90 1574 }
762853f4 1575
a43e4b90 1576 /* multipart messages */
1577 if (count($composeMessage->entities)) {
1578 $message_body = new Message();
a91189d6 1579 $message_body->body_part = $composeMessage->body_part;
1580 $composeMessage->body_part = '';
1581 $mime_header = new MessageHeader;
1582 $mime_header->type0 = 'text';
1583 $mime_header->type1 = 'plain';
1584 if ($special_encoding) {
1585 $mime_header->encoding = $special_encoding;
1c044820 1586 } else {
12a0ed01 1587 $mime_header->encoding = '8bit';
a91189d6 1588 }
1589 if ($default_charset) {
1590 $mime_header->parameters['charset'] = $default_charset;
1591 }
1c044820 1592 $message_body->mime_header = $mime_header;
a43e4b90 1593 array_unshift($composeMessage->entities, $message_body);
a91189d6 1594 $content_type = new ContentType('multipart/mixed');
a43e4b90 1595 } else {
1e2026df 1596 $content_type = new ContentType('text/plain');
1597 if ($special_encoding) {
1598 $rfc822_header->encoding = $special_encoding;
1c044820 1599 } else {
1e2026df 1600 $rfc822_header->encoding = '8bit';
1c044820 1601 }
426e0b72 1602 if ($default_charset) {
1603 $content_type->properties['charset']=$default_charset;
73ad81bf 1604 }
181538ac 1605 }
1c044820 1606
a43e4b90 1607 $rfc822_header->content_type = $content_type;
1608 $composeMessage->rfc822_header = $rfc822_header;
0fdb0aa1 1609 if ($action == 'reply' || $action == 'reply_all') {
1610 global $passed_id, $passed_ent_id;
1611 $reply_id = $passed_id;
1612 $reply_ent_id = $passed_ent_id;
1613 } else {
1614 $reply_id = '';
1615 $reply_ent_id = '';
1616 }
1638beb6 1617
1c044820 1618 /* Here you can modify the message structure just before we hand
6e515418 1619 it over to deliver; plugin authors note that $composeMessage
1620 is sent and modified by reference since 1.5.2 */
1621 do_hook('compose_send', $composeMessage);
a43e4b90 1622
b48d3c53 1623 if (!$useSendmail && !$draft) {
a91189d6 1624 require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
1625 $deliver = new Deliver_SMTP();
783e926e 1626 global $smtpServerAddress, $smtpPort, $pop_before_smtp, $pop_before_smtp_host;
a91189d6 1627
a91189d6 1628 $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
783e926e 1629 if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
9bd3b1e6 1630 get_smtp_user($user, $pass);
a91189d6 1631 $stream = $deliver->initStream($composeMessage,$domain,0,
783e926e 1632 $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host);
b48d3c53 1633 } elseif (!$draft) {
73ad81bf 1634 require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
fd7ab795 1635 global $sendmail_path, $sendmail_args;
f3dc9c62 1636 // Check for outdated configuration
1637 if (!isset($sendmail_args)) {
1638 if ($sendmail_path=='/var/qmail/bin/qmail-inject') {
1639 $sendmail_args = '';
1640 } else {
1641 $sendmail_args = '-i -t';
1642 }
1643 }
fd7ab795 1644 $deliver = new Deliver_SendMail(array('sendmail_args'=>$sendmail_args));
73ad81bf 1645 $stream = $deliver->initStream($composeMessage,$sendmail_path);
b48d3c53 1646 } elseif ($draft) {
73ad81bf 1647 global $draft_folder;
906f7e9f 1648 $imap_stream = sqimap_login($username, false, $imapServerAddress,
73ad81bf 1649 $imapPort, 0);
1650 if (sqimap_mailbox_exists ($imap_stream, $draft_folder)) {
1651 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1652 $imap_deliver = new Deliver_IMAP();
a90d951c 1653 $success = $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $draft_folder);
73ad81bf 1654 sqimap_logout($imap_stream);
1655 unset ($imap_deliver);
c077ffeb 1656 $composeMessage->purgeAttachments();
b67d61ee 1657 return $success;
4dfb9db7 1658 } else {
fd7ab795 1659 $msg = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), htmlspecialchars($draft_folder));
cb34dbd0 1660 plain_error_message($msg);
73ad81bf 1661 return false;
a91189d6 1662 }
a43e4b90 1663 }
0c59bbe1 1664 $success = false;
a43e4b90 1665 if ($stream) {
10adeb76 1666 $deliver->mail($composeMessage, $stream, $reply_id, $reply_ent_id);
0c59bbe1 1667 $success = $deliver->finalizeStream($stream);
a43e4b90 1668 }
0c59bbe1 1669 if (!$success) {
fd7ab795 1670 // $deliver->dlv_server_msg is not always server's reply
6c3d00b5 1671 $msg = _("Message not sent.") . "<br />\n" .
1672 $deliver->dlv_msg;
a15f9d93 1673 if (!empty($deliver->dlv_server_msg)) {
1674 // add 'server replied' part only when it is not empty.
1675 // Delivery error can be generated by delivery class itself
1676 $msg.='<br />' .
1677 _("Server replied:") . ' ' . $deliver->dlv_ret_nr . ' ' .
1678 nl2br(htmlspecialchars($deliver->dlv_server_msg));
1679 }
cb34dbd0 1680 plain_error_message($msg);
a43e4b90 1681 } else {
1682 unset ($deliver);
906f7e9f 1683 $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, 0);
e4a1f097 1684
8780308f 1685
414303b8 1686 // mark as replied or forwarded if applicable
1687 //
1688 global $what, $iAccount, $startMessage, $passed_id, $mailbox;
8780308f 1689
bc29bf70 1690 if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
202bcbcc 1691 require(SM_PATH . 'functions/mailbox_display.php');
8780308f 1692 $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
bc29bf70 1693 switch($action) {
1694 case 'reply':
1695 case 'reply_all':
1696 // check if we are allowed to set the \\Answered flag
1697 if (in_array('\\answered',$aMailbox['PERMANENTFLAGS'], true)) {
1698 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
1699 if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
1700 /**
1701 * Only update the cached headers if the header is
1702 * cached.
1703 */
1704 if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
1705 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
1706 }
1707 }
1708 }
1709 break;
1710 case 'forward':
1711 case 'forward_as_attachment':
1712 // check if we are allowed to set the $Forwarded flag (RFC 4550 paragraph 2.8)
1638beb6 1713 if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
bc29bf70 1714 in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
1715
1716 $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '$Forwarded', true, false);
1717 if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
1718 if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
1719 $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
1720 }
bda07b93 1721 }
8780308f 1722 }
bc29bf70 1723 break;
8780308f 1724 }
bc29bf70 1725
4d1cb59a 1726 /**
1727 * Write mailbox with updated seen flag information back to cache.
1728 */
bc29bf70 1729 if(isset($aUpdatedMsgs[$passed_id])) {
1730 $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
1731 sqsession_register($mailbox_cache,'mailbox_cache');
1732 }
1733
a91189d6 1734 }
414303b8 1735
1736
1737 // move to sent folder
1738 //
1739 $move_to_sent = getPref($data_dir,$username,'move_to_sent');
1740 if (isset($default_move_to_sent) && ($default_move_to_sent != 0)) {
1741 $svr_allow_sent = true;
1742 } else {
1743 $svr_allow_sent = false;
1744 }
1745
1746 if (isset($sent_folder) && (($sent_folder != '') || ($sent_folder != 'none'))
1747 && sqimap_mailbox_exists( $imap_stream, $sent_folder)) {
1748 $fld_sent = true;
1749 } else {
1750 $fld_sent = false;
1751 }
1752
1753 if ((isset($move_to_sent) && ($move_to_sent != 0)) || (!isset($move_to_sent))) {
1754 $lcl_allow_sent = true;
1755 } else {
1756 $lcl_allow_sent = false;
1757 }
1758
1759 if (($fld_sent && $svr_allow_sent && !$lcl_allow_sent) || ($fld_sent && $lcl_allow_sent)) {
1760 if ($action == 'reply' || $action == 'reply_all') {
1761 $save_reply_with_orig=getPref($data_dir,$username,'save_reply_with_orig');
1762 if ($save_reply_with_orig) {
1763 $sent_folder = $mailbox;
1764 }
1765 }
414303b8 1766 require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
1767 $imap_deliver = new Deliver_IMAP();
33f0da43 1768 $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $sent_folder);
414303b8 1769 unset ($imap_deliver);
1770 }
1771
1772
1773 // final cleanup
1774 //
1775 $composeMessage->purgeAttachments();
1776 sqimap_logout($imap_stream);
1777
a43e4b90 1778 }
0c59bbe1 1779 return $success;
a43e4b90 1780}