Source for file read_body.php
Documentation is available at read_body.php
* This file is used for reading the msgs array and displaying
* the resulting emails in the right frame.
* @copyright 1999-2020 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id: read_body.php 14840 2020-01-07 07:42:38Z pdontthink $
/** This is the read_body page */
define('PAGE_NAME', 'read_body');
* Path for SquirrelMail required files.
/* SquirrelMail required files. */
require_once(SM_PATH .
'include/validate.php');
require_once(SM_PATH .
'functions/imap.php');
require_once(SM_PATH .
'functions/mime.php');
require_once(SM_PATH .
'functions/date.php');
require_once(SM_PATH .
'functions/url_parser.php');
require_once(SM_PATH .
'functions/html.php');
* Given an IMAP message id number, this will look it up in the cached
* and sorted msgs array and return the index. Used for finding the next
* @return the index of the next valid message from the array
global $msort, $msgs, $sort,
$thread_sort_messages =
0;
$allow_server_sort =
FALSE;
if ($thread_sort_messages ||
$allow_server_sort) {
$count =
count($server_sort_array) -
1;
foreach($server_sort_array as $key=>
$value) {
if ($passed_id ==
$value) {
$result =
$server_sort_array[$key +
1];
for (reset($msort); ($key =
key($msort)), (isset
($key)); next($msort)) {
if ($passed_id ==
$msgs[$key]['ID']) {
$result =
$msgs[$key]['ID'];
/** returns the index of the previous message from the array. */
global $msort, $sort, $msgs,
$thread_sort_messages =
0;
$allow_server_sort =
FALSE;
if ($thread_sort_messages ||
$allow_server_sort ) {
foreach($server_sort_array as $key=>
$value) {
if ($passed_id ==
$value) {
$result =
$server_sort_array[$key -
1];
for (reset($msort); ($key =
key($msort)), (isset
($key)); next($msort)) {
if ($passed_id ==
$msgs[$key]['ID']) {
$result =
$msgs[$key]['ID'];
* Displays a link to a page where the message is displayed more
// Pull "view_unsafe_images" from the URL to find out if the unsafe images
// should be displayed. The default is not to display unsafe images.
// If "view_unsafe_images" isn't part of the URL, default to not
// displaying unsafe images.
$view_unsafe_images =
false;
// If "view_unsafe_images" is part of the URL, display unsafe images
// regardless of the value of the URL variable.
// FIXME: Do we really want to display the unsafe images regardless of the value in URL variable?
$view_unsafe_images =
true;
$params =
'?passed_ent_id=' .
urlencode($passed_ent_id) .
'&view_unsafe_images='. (bool)
$view_unsafe_images;
$print_text =
_("View Printable Version");
$result =
'<script language="javascript" type="text/javascript">' .
"\n" .
" function printFormat() {\n" .
' window.open("../src/printer_friendly_main.php' .
$params .
'","Print","width=800,height=600");' .
"\n".
"<a href=\"javascript:printFormat();\" style=\"white-space: nowrap;\">$print_text</a>";
$result =
'<a target="_blank" href="../src/printer_friendly_bottom.php' .
"$params\" style=\"white-space: nowrap;\">$print_text</a>";
/* escaping $ doesn't work -> \x36 */
$ret =
preg_match('/(\x36MDNSent|\\\\\*)/i', $read);
function SendMDN ( $mailbox, $passed_id, $sender, $message, $imapConnection) {
$header =
$message->rfc822_header;
$hashed_attachment_dir =
getHashedDir($username, $attachment_dir);
$content_type->properties['report-type']=
'disposition-notification';
$content_type->properties['charset']=
$default_charset;
$rfc822_header->content_type =
$content_type;
$rfc822_header->to[] =
$header->dnt;
$rfc822_header->subject =
_("Read:") .
' ' .
decodeHeader($header->subject, true, false);
// FIXME: use identity.php from SM 1.5. Change this also in compose.php
if (isset
($identity) &&
$identity !=
'default') {
$from_mail =
getPref($data_dir, $username,
'email_address' .
$identity);
$full_name =
getPref($data_dir, $username,
'full_name' .
$identity);
$from_addr =
'"'.
$full_name.
'" <'.
$from_mail.
'>';
$reply_to =
getPref($data_dir, $username,
$from_mail =
getPref($data_dir, $username, 'email_address');
$full_name =
getPref($data_dir, $username, 'full_name');
$from_addr =
'"'.
$full_name.
'" <'.
$from_mail.
'>';
$reply_to =
getPref($data_dir, $username,'reply_to');
// Patch #793504 Return Receipt Failing with <@> from Tim Craig (burny_md)
// This merely comes from compose.php and only happens when there is no
// email_addr specified in user's identity (which is the startup config)
if (preg_match('|^([^@%/]+)[@%/](.+)$|', $username, $usernamedata)) {
$popuser =
$usernamedata[1];
$domain =
$usernamedata[2];
$from_mail =
"$popuser@$domain";
$rfc822_header->from =
$rfc822_header->parseAddress($from_addr,true);
$rfc822_header->reply_to =
$rfc822_header->parseAddress($reply_to,true);
foreach ($to_array as $line) {
$to .=
' '.
$line->getAddress();
$body =
_("Your message") .
"\r\n\r\n" .
"\t" .
_("To") .
': ' .
decodeHeader($to,false,false,true) .
"\r\n" .
"\t" .
_("Subject") .
': ' .
decodeHeader($header->subject,false,false,true) .
"\r\n" .
"\t" .
_("Sent") .
': ' .
$senton .
"\r\n" .
sprintf( _("Was displayed on %s"), $now );
if (isset
($languages[$squirrelmail_language]['XTRA_CODE']) &&
$body =
$languages[$squirrelmail_language]['XTRA_CODE']('encode', $body);
if (strtolower($default_charset) ==
'iso-2022-jp') {
$special_encoding =
'8bit';
$special_encoding =
'7bit';
// detect 8bit symbols added by translations
$special_encoding =
'8bit';
$mime_header->type0 =
'text';
$mime_header->type1 =
'plain';
$mime_header->encoding =
$special_encoding;
$mime_header->encoding =
'7bit';
$mime_header->parameters['charset'] =
$default_charset;
$part1->mime_header =
$mime_header;
$original_recipient =
$to;
$original_message_id =
$header->message_id;
$report =
"Reporting-UA : $SERVER_NAME ; SquirrelMail (version $version) \r\n";
if ($original_recipient !=
'') {
$report .=
"Original-Recipient : $original_recipient\r\n";
$final_recipient =
$sender;
$report .=
"Final-Recipient: rfc822; $final_recipient\r\n" .
"Original-Message-ID : $original_message_id\r\n" .
"Disposition: manual-action/MDN-sent-manually; displayed\r\n";
$part2->setBody($report);
$mime_header->type0 =
'message';
$mime_header->type1 =
'disposition-notification';
$mime_header->encoding =
'7bit';
$part2->mime_header =
$mime_header;
$composeMessage->rfc822_header =
$rfc822_header;
$composeMessage->addEntity($part1);
$composeMessage->addEntity($part2);
require_once(SM_PATH .
'class/deliver/Deliver_SendMail.class.php');
// Check for outdated configuration
if (!isset
($sendmail_args)) {
if ($sendmail_path==
'/var/qmail/bin/qmail-inject') {
$sendmail_args =
'-i -t';
$stream =
$deliver->initStream($composeMessage,$sendmail_path);
require_once(SM_PATH .
'class/deliver/Deliver_SMTP.class.php');
$authPop =
(isset
($pop_before_smtp) &&
$pop_before_smtp) ?
true :
false;
if (empty($pop_before_smtp_host))
$pop_before_smtp_host =
$smtpServerAddress;
$stream =
$deliver->initStream($composeMessage,$domain,0,
$smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host);
$deliver->mail($composeMessage, $stream);
$success =
$deliver->finalizeStream($stream);
$msg =
_("Message not sent.") .
' '.
_("Server replied:") .
"\n<blockquote>\n" .
$deliver->dlv_msg .
'<br />' .
$deliver->dlv_ret_nr .
' ' .
$deliver->dlv_server_msg .
"</blockquote>\n\n";
require_once(SM_PATH .
'functions/display_messages.php');
// copy message to sent folder
$move_to_sent =
getPref($data_dir,$username,'move_to_sent', $default_move_to_sent);
if (isset
($default_move_to_sent) &&
($default_move_to_sent !=
0)) {
if (isset
($sent_folder) &&
(($sent_folder !=
'') ||
($sent_folder !=
'none'))
if ((isset
($move_to_sent) &&
($move_to_sent !=
0)) ||
(!isset
($move_to_sent))) {
if (($fld_sent &&
$svr_allow_sent &&
!$lcl_allow_sent) ||
($fld_sent &&
$lcl_allow_sent)) {
require_once(SM_PATH .
'class/deliver/Deliver_IMAP.class.php');
$imap_deliver->mail($composeMessage, $imapConnection, 0, 0, $imapConnection, $sent_folder);
function ToggleMDNflag ($set ,$imapConnection, $mailbox, $passed_id, $uid_support) {
$cmd =
'STORE ' .
$passed_id .
' ' .
$sg .
'FLAGS ($MDNSent)';
$readmessage, $uid_support);
global $show_more_cc, $show_more, $show_more_bcc,
if ((is_array($recipients)) &&
(isset
($recipients[0]))) {
} else if ($item ==
'cc') {
} else if ($item ==
'bcc') {
$cnt =
count($recipients);
foreach($recipients as $r) {
$string .=
'<br />' .
$add;
$string .=
' (<a href="'.
$url;
$string .=
'">'.
_("less").
'</a>)';
$string .=
'">'.
_("more").
'</a>)';
$show_xmailer_default, $mdn_user_support, $PHP_SELF, $javascript_on,
$header =
$message->rfc822_header;
$from_name =
$header->getAddr_s('from');
$from_name =
$header->getAddr_s('sender');
$from_name =
_("Unknown sender");
if ($default_use_priority) {
if ($show_xmailer_default) {
if ($message->is_mdnsent) {
$env[_("Read receipt")] =
_("sent");
$env[_("Read receipt")] =
_("requested");
$mdn_url =
set_url_var($mdn_url, 'passed_id', $passed_id);
$mdn_url =
set_url_var($mdn_url, 'passed_ent_id', $passed_ent_id);
if ($FirstTimeSee &&
$javascript_on) {
$script =
'<script language="JavaScript" type="text/javascript">' .
"\n";
$script .=
'if(window.confirm("' .
_("The message sender has requested a response to indicate that you have read this message. Would you like to send a receipt?") .
$script .=
'// -->'.
"\n";
$script .=
'</script>'.
"\n";
$env[_("Read receipt")] .=
' <a href="' .
$mdn_url .
'">[' .
_("Send read receipt now") .
']</a>';
$s =
'<table width="100%" cellpadding="0" cellspacing="2" border="0"';
$s .=
' align="center" bgcolor="'.
$color[0].
'">';
foreach ($env as $key =>
$val) {
$s .=
html_tag('td', '<b>' .
$key .
': </b>', 'right', '', 'valign="top" width="20%"') .
"\n";
$s .=
html_tag('td', $val, 'left', '', 'valign="top" width="80%"') .
"\n";
echo
'<table bgcolor="'.
$color[9].
'" width="100%" cellpadding="1"'.
' cellspacing="0" border="0" align="center">'.
"\n";
echo
'<tr><td height="5" colspan="2" bgcolor="'.
$color[4].
'"></td></tr><tr><td align="center">'.
"\n";
formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color);
echo
'</td></tr><tr><td height="5" colspan="2" bgcolor="'.
$color[4].
'"></td></tr>'.
"\n";
function formatMenuBar($mailbox, $passed_id, $passed_ent_id, $message, $mbx_response) {
global $base_uri, $draft_folder, $where, $what, $color, $sort,
$startMessage, $PHP_SELF, $save_as_draft,
$enable_forward_as_attachment;
// wrapping is ok: $topbar_delimiter = ' | ';
$topbar_delimiter =
' | ';
$s =
'<table width="100%" cellpadding="3" cellspacing="0" align="center"'.
' border="0" bgcolor="'.
$color[9].
'"><tr>' .
html_tag( 'td', '', 'left', '', 'width="49%"' ) .
'<small>';
$msgs_url =
$base_uri .
'src/';
if (isset
($where) && isset
($what)) {
'&what=' .
urlencode($what) .
'&mailbox=' .
$urlMailbox;
$msgs_str =
_("Search Results");
$msgs_url .=
'right_main.php?sort=' .
$sort .
'&startMessage=' .
$startMessage .
'&mailbox=' .
$urlMailbox;
$msgs_str =
_("Message List");
$s .=
'<a href="' .
$msgs_url .
'" style="white-space: nowrap;">' .
$msgs_str .
'</a>';
$delete_url =
$base_uri .
'src/delete_message.php?mailbox=' .
$urlMailbox .
$unread_url =
$base_uri .
'src/';
if (!(isset
($passed_ent_id) &&
$passed_ent_id)) {
$unread_url .=
'right_main.php?unread_passed_id=' .
$passed_id .
'&sort=' .
$sort .
'&startMessage=' .
$startMessage .
'&mailbox=' .
$urlMailbox;
$s .=
'<a href="' .
$unread_url .
'">' .
_("Unread") .
'</a>';
$delete_url .=
'sort=' .
$sort .
'&startMessage=' .
$startMessage;
$s .=
'<a href="' .
$delete_url .
'">' .
_("Delete") .
'</a>';
$comp_uri =
'src/compose.php' .
'?passed_id=' .
$passed_id .
'&mailbox=' .
$urlMailbox .
'&startMessage=' .
$startMessage .
(isset
($passed_ent_id)?
'&passed_ent_id='.
urlencode($passed_ent_id):
'');
if (($mailbox ==
$draft_folder) &&
($save_as_draft)) {
$comp_alt_uri =
$comp_uri .
'&smaction=draft';
$comp_alt_string =
_("Resume Draft");
$comp_alt_uri =
$comp_uri .
'&smaction=edit_as_new';
$comp_alt_string =
_("Edit Message as New");
if (isset
($comp_alt_uri)) {
$s .=
makeComposeLink($comp_alt_uri, '<span style="white-space: nowrap;">' .
$comp_alt_string .
'</span>');
$s .=
'</small></td><td align="center" width="2%" style="white-space: nowrap"><small>'
.
(strpos($topbar_delimiter, ' ') ===
0 ?
substr($topbar_delimiter, 6) :
ltrim($topbar_delimiter));
if (!(isset
($where) && isset
($what)) &&
!$passed_ent_id) {
$uri =
$base_uri .
'src/read_body.php?passed_id='.
$prev.
'&mailbox='.
$urlMailbox.
'&sort='.
$sort.
'&startMessage='.
$startMessage;
$s .=
'<a href="'.
$uri.
'">'.
_("Previous").
'</a>';
$uri =
$base_uri .
'src/read_body.php?passed_id='.
$next.
'&mailbox='.
$urlMailbox.
'&sort='.
$sort.
'&startMessage='.
$startMessage;
$s .=
'<a href="'.
$uri.
'">'.
_("Next").
'</a>';
} else if (isset
($passed_ent_id) &&
$passed_ent_id) {
/* code for navigating through attached message/rfc822 messages */
$s .=
'<a href="'.
$url.
'">'.
_("View Message").
'</a>';
foreach($message->parent->entities as $ent) {
if ($ent->type0 ==
'message' &&
$ent->type1 ==
'rfc822') {
$entity_count[$c] =
$ent->entity_id;
$entities[$ent->entity_id] =
$c;
$prev_link =
_("Previous");
if (!empty($entities[$passed_ent_id]) &&
($entities[$passed_ent_id] >
1)) {
$prev_ent_id =
$entity_count[$entities[$passed_ent_id] -
1];
.
set_url_var($PHP_SELF, 'passed_ent_id', $prev_ent_id)
.
'">' .
$prev_link .
'</a>';
if (!empty($entities[$passed_ent_id]) &&
($entities[$passed_ent_id] <
$c)) {
$next_ent_id =
$entity_count[$entities[$passed_ent_id] +
1];
.
set_url_var($PHP_SELF, 'passed_ent_id', $next_ent_id)
.
'">' .
$next_link .
'</a>';
$s .=
$topbar_delimiter .
$prev_link;
$par_ent_id =
$message->parent->entity_id;
$par_ent_id =
substr($par_ent_id,0,-
2);
$url =
set_url_var($PHP_SELF, 'passed_ent_id',$par_ent_id);
$s .=
'<a href="'.
$url.
'">'.
_("Up").
'</a>';
$s .=
$topbar_delimiter .
$next_link;
$s .=
(strrpos($topbar_delimiter, ' ') ===
strlen($topbar_delimiter) -
6 ?
substr($topbar_delimiter, 0, -
6) :
rtrim($topbar_delimiter))
.
'</small></td>' .
"\n" .
html_tag( 'td', '', 'right', '', 'width="49%" ' ) .
'<small>';
$comp_action_uri =
$comp_uri .
'&smaction=forward';
if ($enable_forward_as_attachment) {
$comp_action_uri =
$comp_uri .
'&smaction=forward_as_attachment';
$s .=
makeComposeLink($comp_action_uri, '<span style="white-space: nowrap;">' .
_("Forward as Attachment") .
'</span>');
$comp_action_uri =
$comp_uri .
'&smaction=reply';
$comp_action_uri =
$comp_uri .
'&smaction=reply_all';
$s .=
makeComposeLink($comp_action_uri, '<span style="white-space: nowrap;">' .
_("Reply All") .
'</span>');
$s .=
'</small></td></tr></table>';
function formatToolbar($mailbox, $passed_id, $passed_ent_id, $message, $color) {
global $base_uri, $where, $what, $download_and_unsafe_link;
$urlPassed_ent_id =
urlencode($passed_ent_id);
$query_string =
'mailbox=' .
$urlMailbox .
'&passed_id=' .
$urlPassed_id .
'&passed_ent_id=' .
$urlPassed_ent_id;
$query_string .=
'&where=' .
urlencode($where);
$query_string .=
'&what=' .
urlencode($what);
$url =
$base_uri.
'src/view_header.php?'.
$query_string;
html_tag( 'td', '', 'right', '', 'valign="middle" width="20%"' ) .
'<b>' .
_("Options") .
": </b></td>\n" .
html_tag( 'td', '', 'left', '', 'valign="middle" width="80%"' ) .
'<small>' .
'<a href="'.
$url.
'" style="white-space: nowrap;">'.
_("View Full Header").
'</a>';
/* Output the printer friendly link if we are in subtle mode. */
/* Output the download and/or unsafe images link/-s, if any. */
if ($download_and_unsafe_link) {
echo
$download_and_unsafe_link;
/***************************/
/* Main of read_body.php */
/***************************/
/* get the globals we may need */
$show_more = (int)
$temp;
$show_more_cc = (int)
$temp;
$show_more_bcc = (int)
$temp;
$passed_id = (int)
$temp;
$startMessage = (int)
$temp;
global $uid_support, $sqimap_capabilities;
global $imap_stream_options; // in case not defined in config
$imapConnection =
sqimap_login($username, $key, $imapServerAddress, $imapPort, 0, $imap_stream_options);
* $message contains all information about the message
* including header and body
$uidvalidity =
$mbx_response['UIDVALIDITY'];
if (!isset
($messages[$uidvalidity])) {
$messages[$uidvalidity] =
array();
if (!isset
($messages[$uidvalidity][$passed_id]) ||
!$uid_support) {
$FirstTimeSee =
!$message->is_seen;
$message->is_seen =
true;
$messages[$uidvalidity][$passed_id] =
$message;
// $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
$message =
$messages[$uidvalidity][$passed_id];
$FirstTimeSee =
!$message->is_seen;
if (isset
($passed_ent_id) &&
$passed_ent_id) {
$message =
$message->getEntity($passed_ent_id);
if ($message->type0 !=
'message' &&
$message->type1 !=
'rfc822') {
$message =
$message->parent;
$read =
sqimap_run_command ($imapConnection, "FETCH $passed_id BODY[$passed_ent_id.HEADER]", true, $response, $msg, $uid_support);
$rfc822_header->parseHeader($read);
$message->rfc822_header =
$rfc822_header;
// gmail does not mark messages as read when retrieving the message body
// even though RFC 3501, section 6.4.5 (FETCH Command) says:
// "The \Seen flag is implicitly set; if this causes the flags to change,
// they SHOULD be included as part of the FETCH responses."
if ($imap_server_type ==
'gmail') {
/****************************************/
/* Block for handling incoming url vars */
/****************************************/
if (isset
($sendreceipt)) {
if ( !$message->is_mdnsent ) {
$final_recipient =
getPref($data_dir, $username, 'email_address0', '' );
$final_recipient =
getPref($data_dir, $username, 'email_address', '' );
$final_recipient =
trim($final_recipient);
if ($final_recipient ==
'' ) {
$final_recipient =
getPref($data_dir, $username, 'email_address', '' );
if ( SendMDN( $mailbox, $passed_id, $final_recipient, $message, $imapConnection ) >
0 &&
$supportMDN ) {
ToggleMDNflag( true, $imapConnection, $mailbox, $passed_id, $uid_support);
$message->is_mdnsent =
true;
$messages[$uidvalidity][$passed_id]=
$message;
/***********************************************/
/* End of block for handling incoming url vars */
/***********************************************/
$msgs[$passed_id]['FLAG_SEEN'] =
true;
if ($show_html_default ==
1) {
$ent_ar =
$message->findDisplayEntity(array());
$ent_ar =
$message->findDisplayEntity(array(), array('text/plain'));
for ($i =
0; $i <
$cnt; $i++
) {
$messagebody .=
formatBody($imapConnection, $message, $color, $wrap_at, $ent_ar[$i], $passed_id, $mailbox);
$messagebody .=
'<hr noshade size=1>';
formatMenuBar($mailbox, $passed_id, $passed_ent_id, $message, $mbx_response);
formatEnvheader($mailbox, $passed_id, $passed_ent_id, $message, $color, $FirstTimeSee);
echo
'<table width="100%" cellpadding="0" cellspacing="0" align="center" border="0">';
echo
' <table width="100%" cellpadding="1" cellspacing="0" align="center" border="0" bgcolor="'.
$color[9].
'">';
echo
' <table width="100%" cellpadding="3" cellspacing="0" align="center" border="0">';
echo
' <tr bgcolor="'.
$color[4].
'"><td>';
// echo ' <table cellpadding="1" cellspacing="5" align="left" border="0">';
echo
html_tag( 'table' ,'' , 'left', '', 'cellpadding="1" cellspacing="5" border="0"' );
echo
' <tr>' .
html_tag( 'td', '<br />'.
$messagebody.
"\n", 'left')
echo
' </table></td></tr>';
echo
'<tr><td height="5" colspan="2" bgcolor="'.
$color[4].
'"></td></tr>'.
"\n";
if ($attachmentsdisplay) {
echo
' <table width="100%" cellpadding="1" cellspacing="0" align="center"'.
' border="0" bgcolor="'.
$color[9].
'">';
echo
' <table width="100%" cellpadding="0" cellspacing="0" align="center" border="0" bgcolor="'.
$color[4].
'">';
echo
' <tr>' .
html_tag( 'td', '', 'left', $color[9] );
echo
' <b>' .
_("Attachments") .
':</b>';
$hook_args =
array($message, $mailbox, $passed_id, $passed_ent_id);
echo
' <table width="100%" cellpadding="2" cellspacing="2" align="center"'.
' border="0" bgcolor="'.
$color[0].
'">';
echo
$attachmentsdisplay;
echo
' </td></tr></table>';
echo
' </td></tr></table>';
echo
'<tr><td height="5" colspan="2" bgcolor="'.
$color[4].
'"></td></tr>';
/* show attached images inline -- if pref'fed so */
if (($attachment_common_show_images) &&
is_array($attachment_common_show_images_list)) {
foreach ($attachment_common_show_images_list as $img) {
$imgurl =
SM_PATH .
'src/download.php' .
'passed_id=' .
urlencode($img['passed_id']) .
html_tag( 'td', '<img src="' .
$imgurl .
'" />' .
"\n", 'left'
'center', '', 'cellspacing="0" border="0" cellpadding="2"');
//FIXME: one of these hooks should be removed if we can verify disuse (html_bottom?)
/* sessions are written at the end of the script. it's better to register
them at the end so we avoid double session_register calls */
Documentation generated on Mon, 13 Jan 2020 04:25:12 +0100 by phpDocumentor 1.4.3