summaryrefslogtreecommitdiff
path: root/program/steps/mail
diff options
context:
space:
mode:
Diffstat (limited to 'program/steps/mail')
-rw-r--r--program/steps/mail/attachments.inc43
-rw-r--r--program/steps/mail/compose.inc16
-rw-r--r--program/steps/mail/func.inc35
-rw-r--r--program/steps/mail/list.inc95
-rw-r--r--program/steps/mail/list_contacts.inc2
-rw-r--r--program/steps/mail/search_contacts.inc2
-rw-r--r--program/steps/mail/sendmail.inc27
-rw-r--r--program/steps/mail/show.inc16
8 files changed, 155 insertions, 81 deletions
diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc
index 85bc36cac..c8b7f9517 100644
--- a/program/steps/mail/attachments.inc
+++ b/program/steps/mail/attachments.inc
@@ -60,7 +60,7 @@ if ($RCMAIL->action=='remove-attachment') {
exit;
}
-if ($RCMAIL->action=='display-attachment') {
+if ($RCMAIL->action == 'display-attachment') {
$id = 'undefined';
if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) {
@@ -76,6 +76,47 @@ if ($RCMAIL->action=='display-attachment') {
$attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']);
}
+ // generate image thumbnail for file browser in HTML editor
+ if (!empty($_GET['_thumbnail'])) {
+ $temp_dir = $RCMAIL->config->get('temp_dir');
+ $thumbnail_size = 80;
+ list(,$ext) = explode('/', $attachment['mimetype']);
+ $mimetype = $attachment['mimetype'];
+ $file_ident = $attachment['id'] . ':' . $attachment['mimetype'] . ':' . $attachment['size'];
+ $cache_basename = $temp_dir . '/' . md5($file_ident . ':' . $RCMAIL->user->ID . ':' . $thumbnail_size);
+ $cache_file = $cache_basename . '.' . $ext;
+
+ // render thumbnail image if not done yet
+ if (!is_file($cache_file)) {
+ if (!$attachment['path']) {
+ $orig_name = $filename = $cache_basename . '.orig.' . $ext;
+ file_put_contents($orig_name, $attachment['data']);
+ }
+ else {
+ $filename = $attachment['path'];
+ }
+
+ $image = new rcube_image($filename);
+ if ($imgtype = $image->resize($thumbnail_size, $cache_file, true)) {
+ $mimetype = 'image/' . $imgtype;
+
+ if ($orig_name) {
+ unlink($orig_name);
+ }
+ }
+ }
+
+ if (is_file($cache_file)) {
+ // cache for 1h
+ $RCMAIL->output->future_expire_header(3600);
+ header('Content-Type: ' . $mimetype);
+ header('Content-Length: ' . filesize($cache_file));
+
+ readfile($cache_file);
+ exit;
+ }
+ }
+
header('Content-Type: ' . $attachment['mimetype']);
header('Content-Length: ' . $attachment['size']);
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index a3eb4b8a3..0257f3187 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -951,8 +951,7 @@ function rcmail_compose_body($attrib)
"googie.setLanguages(%s);\n".
"googie.setCurrentLanguage('%s');\n".
"googie.setDecoration(false);\n".
- "googie.decorateTextarea('%s');\n".
- "%s.set_env('spellcheck', googie);",
+ "googie.decorateTextarea('%s');\n",
$RCMAIL->output->get_skin_path(),
$RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)),
!empty($dictionary) ? 'true' : 'false',
@@ -964,14 +963,13 @@ function rcmail_compose_body($attrib)
rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))),
rcube_output::json_serialize($spellcheck_langs),
$lang,
- $attrib['id'],
- rcmail_output::JS_OBJECT_NAME), 'foot');
+ $attrib['id']), 'foot');
$OUTPUT->add_label('checking');
$OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set));
}
- $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>';
+ $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;" aria-hidden="true"></iframe>';
return $out;
}
@@ -1457,6 +1455,9 @@ function rcmail_compose_subject($attrib)
$subject = $MESSAGE->subject;
else
$subject = 'Re: '.$MESSAGE->subject;
+
+ // replace (was: ...) (#1489375)
+ $subject = preg_replace('/\s*\([wW]as:[^\)]+\)\s*$/', '', $subject);
}
// create a forward-subject
else if ($compose_mode == RCUBE_COMPOSE_FORWARD) {
@@ -1701,7 +1702,7 @@ function rcmail_editor_selector($attrib)
if (empty($attrib['name']))
$attrib['name'] = 'editorSelect';
- $attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')";
+ $attrib['onchange'] = "return rcmail.command('toggle-editor', {id: '".$attrib['editorid']."', html: this.value == 'html'}, '', event)";
$select = new html_select($attrib);
@@ -1858,9 +1859,10 @@ function rcmail_compose_responses_list($attrib)
foreach ($RCMAIL->get_compose_responses(true) as $response) {
$key = $response['key'];
$item = html::a(array(
- 'href '=> '#'.urlencode($response['name']),
+ 'href' => '#'.urlencode($response['name']),
'class' => rtrim('insertresponse ' . $attrib['itemclass']),
'unselectable' => 'on',
+ 'tabindex' => '0',
'rel' => $key,
), rcube::Q($response['name']));
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 50b1e8292..ac343ad5a 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -104,6 +104,10 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
}
}
+ if (!empty($_GET['_uid'])) {
+ $OUTPUT->set_env('list_uid', $_GET['_uid']);
+ }
+
// set configuration
$RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted',
'skip_deleted', 'display_next', 'message_extwin', 'compose_extwin', 'forward_attachment'));
@@ -111,7 +115,9 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') {
if (!$OUTPUT->ajax_call) {
$OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
- 'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching');
+ 'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching',
+ 'flagged', 'unflagged', 'unread', 'deleted', 'replied', 'forwarded',
+ 'priority', 'withattachment');
}
$pagetitle = $RCMAIL->localize_foldername($mbox_name, true);
@@ -531,14 +537,19 @@ function rcmail_message_list_head($attrib, $a_show_cols)
$a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc');
if (!empty($attrib['optionsmenuicon'])) {
- $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')";
- if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true')
- $list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu',
- 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')));
- else
- $list_menu = html::a(array('href' => '#', 'onclick' => $onclick),
- html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
- 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))));
+ $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu', this, event)";
+ $inner = $RCMAIL->gettext('listoptions');
+ if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') {
+ $inner = html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'alt' => $RCMAIL->gettext('listoptions')));
+ }
+ $list_menu = html::a(array(
+ 'href' => '#list-options',
+ 'onclick' => $onclick,
+ 'class' => 'listmenu',
+ 'id' => 'listmenulink',
+ 'title' => $RCMAIL->gettext('listoptions'),
+ 'tabindex' => '0',
+ ), $inner);
}
else {
$list_menu = '';
@@ -558,12 +569,14 @@ function rcmail_message_list_head($attrib, $a_show_cols)
// get column name
switch ($col) {
case 'flag':
- $col_name = html::span('flagged', '&nbsp;');
+ $col_name = html::span('flagged', $RCMAIL->gettext('flagged'));
break;
case 'attachment':
case 'priority':
+ $col_name = html::span($col, $RCMAIL->gettext($col));
+ break;
case 'status':
- $col_name = html::span($col, '&nbsp;');
+ $col_name = html::span($col, $RCMAIL->gettext('readstatus'));
break;
case 'threads':
$col_name = $list_menu;
diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc
index 929dda299..496c95146 100644
--- a/program/steps/mail/list.inc
+++ b/program/steps/mail/list.inc
@@ -20,7 +20,7 @@
*/
if (!$OUTPUT->ajax_call) {
- return;
+ return;
}
$save_arr = array();
@@ -28,28 +28,28 @@ $dont_override = (array) $RCMAIL->config->get('dont_override');
// is there a sort type for this request?
if ($sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET)) {
- // yes, so set the sort vars
- list($sort_col, $sort_order) = explode('_', $sort);
-
- // set session vars for sort (so next page and task switch know how to sort)
- if (!in_array('message_sort_col', $dont_override)) {
- $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
- }
- if (!in_array('message_sort_order', $dont_override)) {
- $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
- }
+ // yes, so set the sort vars
+ list($sort_col, $sort_order) = explode('_', $sort);
+
+ // set session vars for sort (so next page and task switch know how to sort)
+ if (!in_array('message_sort_col', $dont_override)) {
+ $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col;
+ }
+ if (!in_array('message_sort_order', $dont_override)) {
+ $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order;
+ }
}
// is there a set of columns for this request?
if ($cols = rcube_utils::get_input_value('_cols', rcube_utils::INPUT_GET)) {
- $_SESSION['list_attrib']['columns'] = explode(',', $cols);
- if (!in_array('list_cols', $dont_override)) {
- $save_arr['list_cols'] = explode(',', $cols);
- }
+ $_SESSION['list_attrib']['columns'] = explode(',', $cols);
+ if (!in_array('list_cols', $dont_override)) {
+ $save_arr['list_cols'] = explode(',', $cols);
+ }
}
if (!empty($save_arr)) {
- $RCMAIL->user->save_prefs($save_arr);
+ $RCMAIL->user->save_prefs($save_arr);
}
$mbox_name = $RCMAIL->storage->get_folder();
@@ -60,27 +60,30 @@ $RCMAIL->storage->folder_sync($mbox_name);
// initialize searching result if search_filter is used
if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') {
- $search_request = md5($mbox_name.$_SESSION['search_scope'].$_SESSION['search_filter']);
- $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column());
- $_SESSION['search'] = $RCMAIL->storage->get_search_set();
- $_SESSION['search_request'] = $search_request;
- $OUTPUT->set_env('search_request', $search_request);
- $OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
+ $search_request = md5($mbox_name.$_SESSION['search_scope'].$_SESSION['search_filter']);
+ $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column());
+
+ $_SESSION['search'] = $RCMAIL->storage->get_search_set();
+ $_SESSION['search_request'] = $search_request;
+
+ $OUTPUT->set_env('search_request', $search_request);
+ $OUTPUT->set_env('search_filter', $_SESSION['search_filter']);
}
// fetch message headers
-if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh'])))
- $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order());
+if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) {
+ $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order());
+}
// update search set (possible change of threading mode)
if (!empty($_REQUEST['_search']) && isset($_SESSION['search'])
&& $_SESSION['search_request'] == $_REQUEST['_search']
) {
- $_SESSION['search'] = $RCMAIL->storage->get_search_set();
+ $_SESSION['search'] = $RCMAIL->storage->get_search_set();
}
// remove old search data
else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) {
- $RCMAIL->session->remove('search');
+ $RCMAIL->session->remove('search');
}
// empty result? we'll skip UNSEEN counting in rcmail_send_unread_count()
@@ -104,33 +107,35 @@ $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_nam
// remove old message rows if commanded by the client
if (!empty($_REQUEST['_clear'])) {
- $OUTPUT->command('clear_message_list');
+ $OUTPUT->command('clear_message_list');
}
// add message rows
rcmail_js_message_list($a_headers, false, $cols);
if (isset($a_headers) && count($a_headers)) {
- if ($search_request) {
- $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
- }
-
- // remember last HIGHESTMODSEQ value (if supported)
- // we need it for flag updates in check-recent
- $data = $RCMAIL->storage->folder_data($mbox_name);
- if (!empty($data['HIGHESTMODSEQ'])) {
- $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
- }
+ if ($search_request) {
+ $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count));
+ }
+
+ // remember last HIGHESTMODSEQ value (if supported)
+ // we need it for flag updates in check-recent
+ $data = $RCMAIL->storage->folder_data($mbox_name);
+ if (!empty($data['HIGHESTMODSEQ'])) {
+ $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ'];
+ }
}
else {
- // handle IMAP errors (e.g. #1486905)
- if ($err_code = $RCMAIL->storage->get_error_code()) {
- $RCMAIL->display_server_error();
- }
- else if ($search_request)
- $OUTPUT->show_message('searchnomatch', 'notice');
- else
- $OUTPUT->show_message('nomessagesfound', 'notice');
+ // handle IMAP errors (e.g. #1486905)
+ if ($err_code = $RCMAIL->storage->get_error_code()) {
+ $RCMAIL->display_server_error();
+ }
+ else if ($search_request) {
+ $OUTPUT->show_message('searchnomatch', 'notice');
+ }
+ else {
+ $OUTPUT->show_message('nomessagesfound', 'notice');
+ }
}
// set trash folder state
diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc
index 0ee81135b..4f17beffd 100644
--- a/program/steps/mail/list_contacts.inc
+++ b/program/steps/mail/list_contacts.inc
@@ -110,7 +110,7 @@ else if (!empty($result) && $result->count > 0) {
$keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
$OUTPUT->command('add_contact_row', $row_id, array(
- $keyname => html::span(array('title' => $email), rcube::Q($name ? $name : $email) .
+ $keyname => html::a(array('title' => $email), rcube::Q($name ? $name : $email) .
($name && count($emails) > 1 ? '&nbsp;' . html::span('email', rcube::Q($email)) : '')
)), $classname);
}
diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc
index d56581695..ccef32dd2 100644
--- a/program/steps/mail/search_contacts.inc
+++ b/program/steps/mail/search_contacts.inc
@@ -87,7 +87,7 @@ if (!empty($result) && $result->count > 0) {
$row_id = $row['ID'].'-'.$i;
$jsresult[$row_id] = format_email_recipient($email, $name);
$OUTPUT->command('add_contact_row', $row_id, array(
- 'contact' => html::span(array('title' => $email), rcube::Q($name ? $name : $email) .
+ 'contact' => html::a(array('title' => $email), rcube::Q($name ? $name : $email) .
($name && count($emails) > 1 ? '&nbsp;' . html::span('email', rcube::Q($email)) : '')
)), 'person');
}
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index baecbd118..b70b18b6b 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -273,9 +273,10 @@ if ($isHtml) {
}
// append doctype and html/body wrappers
- $message_body = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">'
- . "\r\n<html><body" . (!empty($bstyle) ? " style='" . implode($bstyle, '; ') . "'" : '') . ">\r\n"
- . $message_body;
+ $bstyle = !empty($bstyle) ? (" style='" . implode($bstyle, '; ') . "'") : '';
+ $message_body = '<html><head>'
+ . '<meta http-equiv="Content-Type" content="text/html; charset=' . $message_charset . '" /></head>'
+ . "<body" . $bstyle . ">\r\n" . $message_body;
}
if (!$savedraft) {
@@ -310,10 +311,16 @@ if (!$savedraft) {
$COMPOSE['spell_checked'] = true;
if (!$spell_result) {
- $result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml();
+ if ($isHtml) {
+ $result['words'] = $spellchecker->get();
+ $result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary');
+ }
+ else {
+ $result = $spellchecker->get_xml();
+ }
$OUTPUT->show_message('mispellingsfound', 'error');
- $OUTPUT->command('spellcheck_resume', $isHtml, $result);
+ $OUTPUT->command('spellcheck_resume', $result);
$OUTPUT->send('iframe');
}
}
@@ -421,7 +428,7 @@ if (is_array($COMPOSE['attachments'])) {
$attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
if ($isHtml) {
- $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile'
+ $dispurl = '/\s(poster|src)\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile'
. preg_quote($attachment['id']) . '[\s\'"]*/';
$message_body = $MAIL_MIME->getHTMLBody();
$is_inline = preg_match($dispurl, $message_body);
@@ -442,7 +449,7 @@ if (is_array($COMPOSE['attachments'])) {
$cid .= '@localhost';
}
- $message_body = preg_replace($dispurl, ' src="cid:' . $cid . '" ', $message_body);
+ $message_body = preg_replace($dispurl, ' \\1="cid:' . $cid . '" ', $message_body);
$MAIL_MIME->setHTMLBody($message_body);
@@ -738,11 +745,11 @@ function rcmail_get_identity($id)
/**
* go from this:
- * <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
+ * <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*
* to this:
*
- * <img src="/path/on/server/.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
+ * <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" />
*/
function rcmail_fix_emoticon_paths($mime_message)
{
@@ -753,7 +760,7 @@ function rcmail_fix_emoticon_paths($mime_message)
// remove any null-byte characters before parsing
$body = preg_replace('/\x00/', '', $body);
- $searchstr = 'program/js/tiny_mce/plugins/emotions/img/';
+ $searchstr = 'program/js/tinymce/plugins/emoticons/img/';
$offset = 0;
// keep track of added images, so they're only added once
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index beb2cc6e9..e6ab4891b 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -148,11 +148,14 @@ if ($uid) {
if (empty($MESSAGE->headers->flags['SEEN'])
&& ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0))
) {
+ $RCMAIL->output->command('set_unread_message', $MESSAGE->uid, $mbox_name);
$RCMAIL->plugins->exec_hook('message_read', array(
'uid' => $MESSAGE->uid,
'mailbox' => $mbox_name,
'message' => $MESSAGE,
));
+
+ $set_seen_flag = true;
}
}
@@ -174,9 +177,7 @@ else
// mark message as read
-if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) &&
- ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0))
-) {
+if (!empty($set_seen_flag)) {
if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN')) {
if ($count = rcmail_get_unseen_count($mbox_name)) {
rcmail_set_unseen_count($mbox_name, $count - 1);
@@ -198,6 +199,7 @@ function rcmail_message_attachments($attrib)
if (sizeof($MESSAGE->attachments)) {
foreach ($MESSAGE->attachments as $attach_prop) {
$filename = rcmail_attachment_name($attach_prop, true);
+ $size = '';
if ($PRINT_MODE) {
$size = $RCMAIL->message_part_size($attach_prop);
@@ -212,6 +214,10 @@ function rcmail_message_attachments($attrib)
$title = '';
}
+ if ($attach_prop->size) {
+ $size = ' ' . html::span('attachment-size', '(' . $RCMAIL->show_bytes($attach_prop->size) . ')');
+ }
+
$mimetype = rcmail_fix_mimetype($attach_prop->mimetype);
$class = rcube_utils::file2class($mimetype, $filename);
$id = 'attach' . $attach_prop->mime_id;
@@ -221,7 +227,7 @@ function rcmail_message_attachments($attrib)
rcmail_output::JS_OBJECT_NAME, $attach_prop->mime_id),
'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)',
'title' => rcube::Q($title),
- ), rcube::Q($filename));
+ ), rcube::Q($filename) . $size);
$ol .= html::tag('li', array('class' => $class, 'id' => $id), $link);
@@ -350,5 +356,5 @@ function rcmail_message_contactphoto($attrib)
$photo_img = $placeholder ? $placeholder : 'program/resources/blank.gif';
}
- return html::img(array('src' => $photo_img) + $attrib);
+ return html::img(array('src' => $photo_img, 'alt' => $RCMAIL->gettext('contactphoto')) + $attrib);
}