summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthomascube <thomas@roundcube.net>2007-12-10 15:27:19 +0000
committerthomascube <thomas@roundcube.net>2007-12-10 15:27:19 +0000
commitfba1f5ab813f2eb4bedc5d9c4a75e77bbaa90131 (patch)
treecebde4edb06ac3a87eb2306b0c0125610a1bd5ce
parentd39eecad6db1caee97624b80634587d98a75e701 (diff)
New class rcube_user + send message disposition notification
-rw-r--r--.htaccess2
-rw-r--r--CHANGELOG5
-rw-r--r--index.php13
-rw-r--r--program/include/main.inc254
-rw-r--r--program/include/rcmail_template.inc18
-rw-r--r--program/include/rcube_user.inc470
-rw-r--r--program/js/app.js10
-rw-r--r--program/lib/imap.inc82
-rw-r--r--program/lib/rc_mail_mime.inc28
-rw-r--r--program/localization/en_US/labels.inc5
-rw-r--r--program/localization/en_US/messages.inc2
-rw-r--r--program/steps/mail/compose.inc11
-rw-r--r--program/steps/mail/func.inc66
-rw-r--r--program/steps/mail/sendmail.inc111
-rw-r--r--program/steps/mail/sendmdn.inc97
-rw-r--r--program/steps/mail/show.inc3
-rw-r--r--program/steps/settings/delete_identity.inc11
-rw-r--r--program/steps/settings/edit_identity.inc9
-rw-r--r--program/steps/settings/func.inc24
-rw-r--r--program/steps/settings/save_identity.inc107
-rw-r--r--program/steps/settings/save_prefs.inc7
-rw-r--r--skins/default/mail.css12
22 files changed, 870 insertions, 477 deletions
diff --git a/.htaccess b/.htaccess
index b40b7ea8a..4d5bb3d8a 100644
--- a/.htaccess
+++ b/.htaccess
@@ -7,6 +7,7 @@ AddType text/x-component .htc
php_value error_log logs/errors
php_value upload_max_filesize 5M
php_value post_max_size 6M
+ php_value memory_limit 64M
</IfModule>
<IfModule mod_php5.c>
@@ -15,6 +16,7 @@ AddType text/x-component .htc
php_value error_log logs/errors
php_value upload_max_filesize 5M
php_value post_max_size 6M
+ php_value memory_limit 64M
</IfModule>
<FilesMatch "(\.inc|\~)$">
diff --git a/CHANGELOG b/CHANGELOG
index cac1f930d..3fa6b8744 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,11 @@
CHANGELOG RoundCube Webmail
---------------------------
+2007/12/10 (thomasb)
+----------
+- Delegate user-stuff to new class rcube_user
+- Implement Message-Disposition-Notification (Receipts)
+
2007/12/05 (tomekp)
----------
- update bg, uk localization
diff --git a/index.php b/index.php
index ce66d2cd4..9f2d3365e 100644
--- a/index.php
+++ b/index.php
@@ -2,7 +2,7 @@
/*
+-----------------------------------------------------------------------+
| RoundCube Webmail IMAP Client |
- | Version 0.1-20071017 |
+ | Version 0.1-20071210 |
| |
| Copyright (C) 2005-2007, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
@@ -41,7 +41,7 @@
*/
// application constants
-define('RCMAIL_VERSION', '0.1-20071017');
+define('RCMAIL_VERSION', '0.1-20071210');
define('RCMAIL_CHARSET', 'UTF-8');
define('JS_OBJECT_NAME', 'rcmail');
@@ -196,7 +196,7 @@ else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send')
// log in to imap server
-if (!empty($_SESSION['user_id']) && $_task=='mail')
+if (!empty($USER->ID) && $_task=='mail')
{
$conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']);
if (!$conn)
@@ -210,7 +210,7 @@ if (!empty($_SESSION['user_id']) && $_task=='mail')
// not logged in -> set task to 'login
-if (empty($_SESSION['user_id']))
+if (empty($USER->ID))
{
if ($OUTPUT->ajax_call)
$OUTPUT->remote_response("setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);");
@@ -238,7 +238,7 @@ if (!empty($_action))
// not logged in -> show login page
-if (!$_SESSION['user_id'])
+if (empty($USER->ID))
{
$OUTPUT->task = 'login';
$OUTPUT->send('login');
@@ -274,6 +274,9 @@ if ($_task=='mail')
if ($_action=='viewsource')
include('program/steps/mail/viewsource.inc');
+ if ($_action=='sendmdn')
+ include('program/steps/mail/sendmdn.inc');
+
if ($_action=='send')
include('program/steps/mail/sendmail.inc');
diff --git a/program/include/main.inc b/program/include/main.inc
index 55cd8efce..7892d0924 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -29,6 +29,7 @@
require_once('lib/des.inc');
require_once('lib/utf7.inc');
require_once('lib/utf8.class.php');
+require_once('include/rcube_user.inc');
require_once('include/rcube_shared.inc');
require_once('include/rcmail_template.inc');
@@ -48,7 +49,7 @@ define('RCUBE_INPUT_GPC', 0x0103);
function rcmail_startup($task='mail')
{
global $sess_id, $sess_user_lang;
- global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB;
+ global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $USER;
// check client
$BROWSER = rcube_browser();
@@ -87,6 +88,8 @@ function rcmail_startup($task='mail')
// set session vars global
$sess_user_lang = rcube_language_prop($_SESSION['user_lang']);
+ // create user object
+ $USER = new rcube_user($_SESSION['user_id']);
// overwrite config with user preferences
if (is_array($_SESSION['user_prefs']))
@@ -321,21 +324,18 @@ function rcmail_shutdown()
*/
function rcmail_kill_session()
{
- // save user preferences
- $a_user_prefs = $_SESSION['user_prefs'];
- if (!is_array($a_user_prefs))
- $a_user_prefs = array();
-
+ global $USER;
+
if ((isset($_SESSION['sort_col']) && $_SESSION['sort_col']!=$a_user_prefs['message_sort_col']) ||
(isset($_SESSION['sort_order']) && $_SESSION['sort_order']!=$a_user_prefs['message_sort_order']))
{
- $a_user_prefs['message_sort_col'] = $_SESSION['sort_col'];
- $a_user_prefs['message_sort_order'] = $_SESSION['sort_order'];
- rcmail_save_user_prefs($a_user_prefs);
+ $a_user_prefs = array('message_sort_col' => $_SESSION['sort_col'], 'message_sort_order' => $_SESSION['sort_order']);
+ $USER->save_prefs($a_user_prefs);
}
$_SESSION = array('user_lang' => $GLOBALS['sess_user_lang'], 'auth_time' => time(), 'temp' => true);
setcookie('sessauth', '-del-', time()-60);
+ $USER->reset();
}
@@ -531,7 +531,7 @@ function rcmail_autoselect_host()
*/
function rcmail_login($user, $pass, $host=NULL)
{
- global $CONFIG, $IMAP, $DB, $sess_user_lang;
+ global $CONFIG, $IMAP, $DB, $USER, $sess_user_lang;
$user_id = NULL;
if (!$host)
@@ -583,58 +583,51 @@ function rcmail_login($user, $pass, $host=NULL)
// try to resolve email address from virtuser table
if (!empty($CONFIG['virtuser_file']) && strpos($user, '@'))
- $user = rcmail_email2user($user);
+ $user = rcube_user::email2user($user);
// lowercase username if it's an e-mail address (#1484473)
if (strpos($user, '@'))
$user = strtolower($user);
// query if user already registered
- $sql_result = $DB->query(
- "SELECT user_id, username, language, preferences
- FROM ".get_table_name('users')."
- WHERE mail_host=? AND (username=? OR alias=?)",
- $host,
- $user,
- $user);
+ if ($existing = rcube_user::query($user, $host))
+ $USER = $existing;
// user already registered -> overwrite username
- if ($sql_arr = $DB->fetch_assoc($sql_result))
+ if ($USER->ID)
{
- $user_id = $sql_arr['user_id'];
- $user = $sql_arr['username'];
+ $user_id = $USER->ID;
+ $user = $USER->data['username'];
}
// exit if IMAP login failed
if (!($imap_login = $IMAP->connect($host, $user, $pass, $imap_port, $imap_ssl)))
- return FALSE;
+ return false;
// user already registered
- if ($user_id && !empty($sql_arr))
+ if ($USER->ID)
{
// get user prefs
- if (strlen($sql_arr['preferences']))
- {
- $user_prefs = unserialize($sql_arr['preferences']);
- $_SESSION['user_prefs'] = $user_prefs;
- array_merge($CONFIG, $user_prefs);
- }
-
+ $_SESSION['user_prefs'] = $USER->get_prefs();
+ array_merge($CONFIG, $_SESSION['user_prefs']);
// set user specific language
- if (strlen($sql_arr['language']))
- $sess_user_lang = $_SESSION['user_lang'] = $sql_arr['language'];
+ if (!empty($USER->data['language']))
+ $sess_user_lang = $_SESSION['user_lang'] = $USER->data['language'];
// update user's record
- $DB->query("UPDATE ".get_table_name('users')."
- SET last_login=".$DB->now()."
- WHERE user_id=?",
- $user_id);
+ $USER->touch();
}
// create new system user
else if ($CONFIG['auto_create_user'])
{
- $user_id = rcmail_create_user($user, $host);
+ if ($created = rcube_user::create($user, $host))
+ {
+ $USER = $created;
+
+ // get existing mailboxes
+ $a_mailboxes = $IMAP->list_mailboxes();
+ }
}
else
{
@@ -646,13 +639,13 @@ function rcmail_login($user, $pass, $host=NULL)
), true, false);
}
- if ($user_id)
+ if ($USER->ID)
{
- $_SESSION['user_id'] = $user_id;
+ $_SESSION['user_id'] = $USER->ID;
+ $_SESSION['username'] = $USER->data['username'];
$_SESSION['imap_host'] = $host;
$_SESSION['imap_port'] = $imap_port;
$_SESSION['imap_ssl'] = $imap_ssl;
- $_SESSION['username'] = $user;
$_SESSION['user_lang'] = $sess_user_lang;
$_SESSION['password'] = encrypt_passwd($pass);
$_SESSION['login_time'] = mktime();
@@ -672,83 +665,6 @@ function rcmail_login($user, $pass, $host=NULL)
/**
- * Create new entry in users and identities table
- *
- * @param string User name
- * @param string IMAP host
- * @return mixed New user ID or False on failure
- */
-function rcmail_create_user($user, $host)
-{
- global $DB, $CONFIG, $IMAP;
-
- $user_email = '';
-
- // try to resolve user in virtusertable
- if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@'))
- $user_email = rcmail_user2email($user);
-
- $DB->query("INSERT INTO ".get_table_name('users')."
- (created, last_login, username, mail_host, alias, language)
- VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)",
- strip_newlines($user),
- strip_newlines($host),
- strip_newlines($user_email),
- $_SESSION['user_lang']);
-
- if ($user_id = $DB->insert_id(get_sequence_name('users')))
- {
- $mail_domain = rcmail_mail_domain($host);
-
- if ($user_email=='')
- $user_email = strpos($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain);
-
- $user_name = $user!=$user_email ? $user : '';
-
- // try to resolve the e-mail address from the virtuser table
- if (!empty($CONFIG['virtuser_query']) &&
- ($sql_result = $DB->query(preg_replace('/%u/', $DB->escapeSimple($user), $CONFIG['virtuser_query']))) &&
- ($DB->num_rows()>0))
- {
- while ($sql_arr = $DB->fetch_array($sql_result))
- {
- $DB->query("INSERT INTO ".get_table_name('identities')."
- (user_id, del, standard, name, email)
- VALUES (?, 0, 1, ?, ?)",
- $user_id,
- strip_newlines($user_name),
- preg_replace('/^@/', $user . '@', $sql_arr[0]));
- }
- }
- else
- {
- // also create new identity records
- $DB->query("INSERT INTO ".get_table_name('identities')."
- (user_id, del, standard, name, email)
- VALUES (?, 0, 1, ?, ?)",
- $user_id,
- strip_newlines($user_name),
- strip_newlines($user_email));
- }
-
- // get existing mailboxes
- $a_mailboxes = $IMAP->list_mailboxes();
- }
- else
- {
- raise_error(array(
- 'code' => 500,
- 'type' => 'php',
- 'line' => __LINE__,
- 'file' => __FILE__,
- 'message' => "Failed to create new user"), TRUE, FALSE);
- }
-
- return $user_id;
-}
-
-
-/**
* Load virtuser table in array
*
* @return array Virtuser table entries
@@ -794,90 +710,6 @@ function rcmail_findinvirtual($pattern)
/**
- * Resolve username using a virtuser table
- *
- * @param string E-mail address to resolve
- * @return string Resolved IMAP username
- */
-function rcmail_email2user($email)
- {
- $user = $email;
- $r = rcmail_findinvirtual("^$email");
-
- for ($i=0; $i<count($r); $i++)
- {
- $data = $r[$i];
- $arr = preg_split('/\s+/', $data);
- if(count($arr)>0)
- {
- $user = trim($arr[count($arr)-1]);
- break;
- }
- }
-
- return $user;
- }
-
-
-/**
- * Resolve e-mail address from virtuser table
- *
- * @param string User name
- * @return string Resolved e-mail address
- */
-function rcmail_user2email($user)
- {
- $email = "";
- $r = rcmail_findinvirtual("$user$");
-
- for ($i=0; $i<count($r); $i++)
- {
- $data=$r[$i];
- $arr = preg_split('/\s+/', $data);
- if (count($arr)>0)
- {
- $email = trim($arr[0]);
- break;
- }
- }
-
- return $email;
- }
-
-
-/**
- * Write the given user prefs to the user's record
- *
- * @param mixed User prefs to save
- * @return boolean True on success, False on failure
- */
-function rcmail_save_user_prefs($a_user_prefs)
- {
- global $DB, $CONFIG, $sess_user_lang;
-
- // merge (partial) prefs array with existing settings
- $a_user_prefs += (array)$_SESSION['user_prefs'];
-
- $DB->query("UPDATE ".get_table_name('users')."
- SET preferences=?,
- language=?
- WHERE user_id=?",
- serialize($a_user_prefs),
- $sess_user_lang,
- $_SESSION['user_id']);
-
- if ($DB->affected_rows())
- {
- $_SESSION['user_prefs'] = $a_user_prefs;
- $CONFIG = array_merge($CONFIG, $a_user_prefs);
- return TRUE;
- }
-
- return FALSE;
- }
-
-
-/**
* Overwrite action variable
*
* @param string New action value
@@ -1514,6 +1346,26 @@ function rcmail_mod_css_styles($source, $container_id, $base_url = '')
return $styles;
}
+/**
+ * Try to autodetect operating system and find the correct line endings
+ *
+ * @return string The appropriate mail header delimiter
+ */
+function rcmail_header_delm()
+{
+ global $CONFIG;
+
+ // use the configured delimiter for headers
+ if (!empty($CONFIG['mail_header_delimiter']))
+ return $CONFIG['mail_header_delimiter'];
+ else if (strtolower(substr(PHP_OS, 0, 3)=='win'))
+ return "\r\n";
+ else if (strtolower(substr(PHP_OS, 0, 3)=='mac'))
+ return "\r\n";
+ else
+ return "\n";
+}
+
/**
* Compose a valid attribute string for HTML tags
diff --git a/program/include/rcmail_template.inc b/program/include/rcmail_template.inc
index 558bd4bf6..cc5a58ac1 100644
--- a/program/include/rcmail_template.inc
+++ b/program/include/rcmail_template.inc
@@ -761,27 +761,15 @@ function rcmail_message_container($attrib)
*/
function rcmail_current_username($attrib)
{
- global $DB;
+ global $USER;
static $s_username;
// alread fetched
if (!empty($s_username))
return $s_username;
- // get e-mail address form default identity
- $sql_result = $DB->query(
- "SELECT email AS mailto
- FROM ".get_table_name('identities')."
- WHERE user_id=?
- AND standard=1
- AND del<>1",
- $_SESSION['user_id']);
-
- if ($DB->num_rows($sql_result))
- {
- $sql_arr = $DB->fetch_assoc($sql_result);
- $s_username = $sql_arr['mailto'];
- }
+ if ($sql_arr = $USER->get_identity())
+ $s_username = $sql_arr['email'];
else if (strstr($_SESSION['username'], '@'))
$s_username = $_SESSION['username'];
else
diff --git a/program/include/rcube_user.inc b/program/include/rcube_user.inc
new file mode 100644
index 000000000..841c84341
--- /dev/null
+++ b/program/include/rcube_user.inc
@@ -0,0 +1,470 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/include/rcube_user.inc |
+ | |
+ | This file is part of the RoundCube Webmail client |
+ | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland |
+ | Licensed under the GNU GPL |
+ | |
+ | PURPOSE: |
+ | This class represents a system user linked and provides access |
+ | to the related database records. |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+
+ $Id: rcube_user.inc 933 2007-11-29 14:17:32Z thomasb $
+
+*/
+
+
+/**
+ * Class representing a system user
+ *
+ * @package core
+ * @author Thomas Bruederli <roundcube@gmail.com>
+ */
+class rcube_user
+{
+ var $ID = null;
+ var $data = null;
+
+
+ /**
+ * Object constructor
+ *
+ * @param object DB Database connection
+ */
+ function __construct($id = null, $sql_arr = null)
+ {
+ global $DB;
+
+ if ($id && !$sql_arr)
+ {
+ $sql_result = $DB->query("SELECT * FROM ".get_table_name('users')." WHERE user_id=?", $id);
+ $sql_arr = $DB->fetch_assoc($sql_result);
+ }
+
+ if (!empty($sql_arr))
+ {
+ $this->ID = $sql_arr['user_id'];
+ $this->data = $sql_arr;
+ }
+ }
+
+ /**
+ * PHP 4 object constructor
+ *
+ * @see rcube_user::__construct
+ */
+ function rcube_user($id = null, $sql_arr = null)
+ {
+ $this->__construct($id, $sql_arr);
+ }
+
+
+ /**
+ * Build a user name string (as e-mail address)
+ *
+ * @return string Full user name
+ */
+ function get_username()
+ {
+ return $this->data['username'] ? $this->data['username'] . (!strpos($this->data['username'], '@') ? '@'.$this->data['mail_host'] : '') : false;
+ }
+
+
+ /**
+ * Get the preferences saved for this user
+ *
+ * @return array Hash array with prefs
+ */
+ function get_prefs()
+ {
+ if ($this->ID && $this->data['preferences'])
+ return unserialize($this->data['preferences']);
+ else
+ return array();
+ }
+
+
+ /**
+ * Write the given user prefs to the user's record
+ *
+ * @param mixed User prefs to save
+ * @return boolean True on success, False on failure
+ */
+ function save_prefs($a_user_prefs)
+ {
+ global $DB, $CONFIG, $sess_user_lang;
+
+ if (!$this->ID)
+ return false;
+
+ // merge (partial) prefs array with existing settings
+ $a_user_prefs += (array)$this->get_prefs();
+
+ $DB->query(
+ "UPDATE ".get_table_name('users')."
+ SET preferences=?,
+ language=?
+ WHERE user_id=?",
+ serialize($a_user_prefs),
+ $sess_user_lang,
+ $this->ID);
+
+ if ($DB->affected_rows())
+ {
+ $CONFIG = array_merge($CONFIG, $a_user_prefs);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Get default identity of this user
+ *
+ * @param int Identity ID. If empty, the default identity is returned
+ * @return array Hash array with all cols of the
+ */
+ function get_identity($id = null)
+ {
+ global $DB;
+
+ $sql_result = $this->list_identities($id ? sprintf('AND identity_id=%d', $id) : '');
+ return $DB->fetch_assoc($sql_result);
+ }
+
+
+ /**
+ * Return a list of all identities linked with this user
+ *
+ * @return array List of identities
+ */
+ function list_identities($sql_add = '')
+ {
+ global $DB;
+
+ // get contacts from DB
+ $sql_result = $DB->query(
+ "SELECT * FROM ".get_table_name('identities')."
+ WHERE del<>1
+ AND user_id=?
+ $sql_add
+ ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC",
+ $this->ID);
+
+ return $sql_result;
+ }
+
+
+ /**
+ * Update a specific identity record
+ *
+ * @param int Identity ID
+ * @param array Hash array with col->value pairs to save
+ * @return boolean True if saved successfully, false if nothing changed
+ */
+ function update_identity($iid, $data)
+ {
+ global $DB;
+
+ if (!$this->ID)
+ return false;
+
+ $write_sql = array();
+
+ foreach ((array)$data as $col => $value)
+ {
+ $write_sql[] = sprintf("%s=%s",
+ $DB->quoteIdentifier($col),
+ $DB->quote($value));
+ }
+
+ $DB->query(
+ "UPDATE ".get_table_name('identities')."
+ SET ".join(', ', $write_sql)."
+ WHERE identity_id=?
+ AND user_id=?
+ AND del<>1",
+ $iid,
+ $this->ID);
+
+ return $DB->affected_rows();
+ }
+
+
+ /**
+ * Create a new identity record linked with this user
+ *
+ * @param array Hash array with col->value pairs to save
+ * @return int The inserted identity ID or false on error
+ */
+ function insert_identity($data)
+ {
+ global $DB;
+
+ if (!$this->ID)
+ return false;
+
+ $insert_cols = $insert_values = array();
+ foreach ((array)$data as $col => $value)
+ {
+ $insert_cols[] = $DB->quoteIdentifier($col);
+ $insert_values[] = $DB->quote($value);
+ }
+
+ $DB->query(
+ "INSERT INTO ".get_table_name('identities')."
+ (user_id, ".join(', ', $insert_cols).")
+ VALUES (?, ".join(', ', $insert_values).")",
+ $this->ID);
+
+ return $DB->insert_id(get_sequence_name('identities'));
+ }
+
+
+ /**
+ * Mark the given identity as deleted
+ *
+ * @param int Identity ID
+ * @return boolean True if deleted successfully, false if nothing changed
+ */
+ function delete_identity($iid)
+ {
+ global $DB;
+
+ if (!$this->ID)
+ return false;
+
+ $DB->query(
+ "UPDATE ".get_table_name('identities')."
+ SET del=1
+ WHERE user_id=?
+ AND identity_id=?",
+ $this->ID,
+ $iid);
+
+ return $DB->affected_rows();
+ }
+
+
+ /**
+ * Make this identity the default one for this user
+ *
+ * @param int The identity ID
+ */
+ function set_default($iid)
+ {
+ global $DB;
+
+ if ($this->ID && $iid)
+ {
+ $DB->query(
+ "UPDATE ".get_table_name('identities')."
+ SET ".$DB->quoteIdentifier('standard')."='0'
+ WHERE user_id=?
+ AND identity_id<>?
+ AND del<>1",
+ $this->ID,
+ $iid);
+ }
+ }
+
+
+ /**
+ * Update user's last_login timestamp
+ */
+ function touch()
+ {
+ global $DB;
+
+ if ($this->ID)
+ {
+ $DB->query(
+ "UPDATE ".get_table_name('users')."
+ SET last_login=".$DB->now()."
+ WHERE user_id=?",
+ $this->ID);
+ }
+ }
+
+
+ /**
+ * Clear the saved object state
+ */
+ function reset()
+ {
+ $this->ID = null;
+ $this->data = null;
+ }
+
+
+ /**
+ * Find a user record matching the given name and host
+ *
+ * @param string IMAP user name
+ * @param string IMAP host name
+ * @return object rcube_user New user instance
+ * @static
+ */
+ function query($user, $host)
+ {
+ global $DB;
+
+ // query if user already registered
+ $sql_result = $DB->query(
+ "SELECT * FROM ".get_table_name('users')."
+ WHERE mail_host=? AND (username=? OR alias=?)",
+ $host,
+ $user,
+ $user);
+
+ // user already registered -> overwrite username
+ if ($sql_arr = $DB->fetch_assoc($sql_result))
+ return new rcube_user($sql_arr['user_id'], $sql_arr);
+ else
+ return false;
+ }
+
+
+ /**
+ * Create a new user record and return a rcube_user instance
+ *
+ * @param string IMAP user name
+ * @param string IMAP host
+ * @return object rcube_user New user instance
+ * @static
+ */
+ function create($user, $host)
+ {
+ global $DB, $CONFIG;
+
+ $user_email = '';
+
+ // try to resolve user in virtusertable
+ if (!empty($CONFIG['virtuser_file']) && !strpos($user, '@'))
+ $user_email = self::user2email($user);
+
+ $DB->query(
+ "INSERT INTO ".get_table_name('users')."
+ (created, last_login, username, mail_host, alias, language)
+ VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)",
+ strip_newlines($user),
+ strip_newlines($host),
+ strip_newlines($user_email),
+ $_SESSION['user_lang']);
+
+ if ($user_id = $DB->insert_id(get_sequence_name('users')))
+ {
+ $mail_domain = rcmail_mail_domain($host);
+
+ if ($user_email=='')
+ $user_email = strpos($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain);
+
+ $user_name = $user != $user_email ? $user : '';
+
+ // try to resolve the e-mail address from the virtuser table
+ if (!empty($CONFIG['virtuser_query']) &&
+ ($sql_result = $DB->query(preg_replace('/%u/', $DB->escapeSimple($user), $CONFIG['virtuser_query']))) &&
+ ($DB->num_rows()>0))
+ {
+ while ($sql_arr = $DB->fetch_array($sql_result))
+ {
+ $DB->query(
+ "INSERT INTO ".get_table_name('identities')."
+ (user_id, del, standard, name, email)
+ VALUES (?, 0, 1, ?, ?)",
+ $user_id,
+ strip_newlines($user_name),
+ preg_replace('/^@/', $user . '@', $sql_arr[0]));
+ }
+ }
+ else
+ {
+ // also create new identity records
+ $DB->query(
+ "INSERT INTO ".get_table_name('identities')."
+ (user_id, del, standard, name, email)
+ VALUES (?, 0, 1, ?, ?)",
+ $user_id,
+ strip_newlines($user_name),
+ strip_newlines($user_email));
+ }
+ }
+ else
+ {
+ raise_error(array(
+ 'code' => 500,
+ 'type' => 'php',
+ 'line' => __LINE__,
+ 'file' => __FILE__,
+ 'message' => "Failed to create new user"), true, false);
+ }
+
+ return $user_id ? new rcube_user($user_id) : false;
+ }
+
+
+ /**
+ * Resolve username using a virtuser table
+ *
+ * @param string E-mail address to resolve
+ * @return string Resolved IMAP username
+ * @static
+ */
+ function email2user($email)
+ {
+ $user = $email;
+ $r = rcmail_findinvirtual("^$email");
+
+ for ($i=0; $i<count($r); $i++)
+ {
+ $data = $r[$i];
+ $arr = preg_split('/\s+/', $data);
+ if (count($arr) > 0)
+ {
+ $user = trim($arr[count($arr)-1]);
+ break;
+ }
+ }
+
+ return $user;
+ }
+
+
+ /**
+ * Resolve e-mail address from virtuser table
+ *
+ * @param string User name
+ * @return string Resolved e-mail address
+ * @static
+ */
+ function user2email($user)
+ {
+ $email = "";
+ $r = rcmail_findinvirtual("$user$");
+
+ for ($i=0; $i<count($r); $i++)
+ {
+ $data = $r[$i];
+ $arr = preg_split('/\s+/', $data);
+ if (count($arr) > 0)
+ {
+ $email = trim($arr[0]);
+ break;
+ }
+ }
+
+ return $email;
+ }
+
+}
+
+
+?>
diff --git a/program/js/app.js b/program/js/app.js
index 7162795fe..f0065acf5 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -223,6 +223,16 @@ function rcube_webmail()
this.gui_objects.folderlist = this.gui_objects.mailboxlist;
this.http_request('getunread', '');
}
+
+ // ask user to send MDN
+ if (this.env.mdn_request && this.env.uid)
+ {
+ var mdnurl = '_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox);
+ if (confirm(this.get_label('mdnrequest')))
+ this.http_post('sendmdn', mdnurl);
+ else
+ this.http_post('mark', mdnurl+'&_flag=mdnsent');
+ }
break;
diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index fef0b8b5d..c5940773d 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -1255,6 +1255,7 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false){
$result[$id]=new iilBasicHeader;
$result[$id]->id = $id;
$result[$id]->subject = "";
+ $result[$id]->messageID = "mid:".$id;
/*
Start parsing headers. The problem is, some header "lines" take up multiple lines.
So, we'll read ahead, and if the one we're reading now is a valid header, we'll
@@ -1293,38 +1294,63 @@ function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false){
}
// create array with header field:data
- $headers = array();
while ( list($lines_key, $str) = each($lines) ){
list($field, $string) = iil_SplitHeaderLine($str);
$field = strtolower($field);
- $headers[$field] = $string;
- }
- $result[$id]->date = $headers["date"];
- $result[$id]->timestamp = iil_StrToTime($headers["date"]);
- $result[$id]->from = $headers["from"];
- $result[$id]->to = str_replace("\n", " ", $headers["to"]);
- $result[$id]->subject = str_replace("\n", "", $headers["subject"]);
- $result[$id]->replyto = str_replace("\n", " ", $headers["reply-to"]);
- $result[$id]->cc = str_replace("\n", " ", $headers["cc"]);
- $result[$id]->bcc = str_replace("\n", " ", $headers["bcc"]);
- $result[$id]->encoding = str_replace("\n", " ", $headers["content-transfer-encoding"]);
- $result[$id]->ctype = str_replace("\n", " ", $headers["content-type"]);
- $result[$id]->in_reply_to = ereg_replace("[\n<>]",'', $headers['in-reply-to']);
- $result[$id]->references = $headers["references"];
- $result[$id]->mdn_to = $headers["disposition-notification-to"];
-
- list($result[$id]->ctype, $ctype_add) = explode(";", $headers["content-type"]);
-
- if (preg_match('/charset="?([a-z0-9\-]+)"?/i', $ctype_add, $regs))
- $result[$id]->charset = $regs[1];
-
- $messageID = $headers["message-id"];
- if (!$messageID) "mid:".$id;
- $result[$id]->messageID = $messageID;
+
+ switch ($field){
+ case 'date';
+ $result[$id]->date = $string;
+ $result[$id]->timestamp = iil_StrToTime($string);
+ break;
+ case 'from':
+ $result[$id]->from = $string;
+ break;
+ case 'to':
+ $result[$id]->to = str_replace("\n", " ", $string);
+ break;
+ case 'subject':
+ $result[$id]->subject = str_replace("\n", "", $string);
+ break;
+ case 'reply-to':
+ $result[$id]->replyto = str_replace("\n", " ", $string);
+ break;
+ case 'cc':
+ $result[$id]->cc = str_replace("\n", " ", $string);
+ break;
+ case 'bcc':
+ $result[$id]->bcc = str_replace("\n", " ", $string);
+ break;
+ case 'content-transfer-encoding':
+ $result[$id]->encoding = str_replace("\n", " ", $string);
+ break;
+ case 'content-type':
+ $ctype_parts = explode(";", $string);
+ $result[$id]->ctype = array_shift($ctype_parts);
+ foreach ($ctype_parts as $ctype_add)
+ if (preg_match('/charset="?([a-z0-9\-]+)"?/i', $ctype_add, $regs))
+ $result[$id]->charset = $regs[1];
+ break;
+ case 'in-reply-to':
+ $result[$id]->in_reply_to = ereg_replace("[\n<>]", '', $string);
+ break;
+ case 'references':
+ $result[$id]->references = $string;
+ break;
+ case 'return-receipt-to':
+ case 'disposition-notification-to':
+ case 'x-confirm-reading-to':
+ $result[$id]->mdn_to = str_replace("\n", " ", $string);
+ break;
+ case 'message-id':
+ $result[$id]->messageID = $string;
+ break;
+ }
}
- else {
- $a=explode(" ", $line);
- }
+ }
+ else {
+ $a=explode(" ", $line);
+ }
}
}while(strcmp($a[0], $key)!=0);
diff --git a/program/lib/rc_mail_mime.inc b/program/lib/rc_mail_mime.inc
index 12d80bbfb..ca4d0bf93 100644
--- a/program/lib/rc_mail_mime.inc
+++ b/program/lib/rc_mail_mime.inc
@@ -25,6 +25,14 @@ require_once('Mail/mime.php');
class rc_mail_mime extends Mail_mime
{
+ /**
+ * Set build parameters
+ */
+ function setParam($param)
+ {
+ if (is_array($param))
+ $this->_build_params = array_merge($this->_build_params, $param);
+ }
/**
* Adds an image to the list of embedded images.
@@ -63,7 +71,7 @@ class rc_mail_mime extends Mail_mime
return true;
}
-
+
/**
* returns the HTML body portion of the message
@@ -77,6 +85,22 @@ class rc_mail_mime extends Mail_mime
/**
+ * Creates a new mimePart object, using multipart/mixed as
+ * the initial content-type and returns it during the
+ * build process.
+ *
+ * @return object The multipart/mixed mimePart object
+ * @access private
+ */
+ function &_addMixedPart()
+ {
+ $params['content_type'] = $this->_headers['Content-Type'] ? $this->_headers['Content-Type'] : 'multipart/mixed';
+ $ret = new Mail_mimePart('', $params);
+ return $ret;
+ }
+
+
+ /**
* Encodes a header as per RFC2047
*
* @param array $input The header data to encode
@@ -138,7 +162,7 @@ class rc_mail_mime extends Mail_mime
// add chunk to output string by regarding the header maxlen
$len = strlen($value);
- if ($line_len + $len < $maxlen)
+ if ($i == 0 || $line_len + $len < $maxlen)
{
$hdr_value .= ($i>0?', ':'') . $value;
$line_len += $len + ($i>0?2:0);
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index e4f04f95e..0b8213759 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -160,6 +160,11 @@ $labels['addcc'] = 'Add Cc';
$labels['addbcc'] = 'Add Bcc';
$labels['addreplyto'] = 'Add Reply-To';
+// mdn
+$labels['mdnrequest'] = 'The sender of this message has asked to be notified when you read this message. Do you wish to notify the sender?';
+$labels['receiptread'] = 'Return Receipt (read)';
+$labels['yourmessage'] = 'This is a Return Receipt for your message';
+$labels['receiptnote'] = 'Note: This receipt only acknowledges that the message was displayed on the recipient\'s computer. There is no guarantee that the recipient has read or understood the message contents.';
// address boook
$labels['name'] = 'Display name';
diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc
index 601075771..119e59512 100644
--- a/program/localization/en_US/messages.inc
+++ b/program/localization/en_US/messages.inc
@@ -74,5 +74,7 @@ $messages['copyerror'] = 'Could not copy any addresses';
$messages['sourceisreadonly'] = 'This address source is read only';
$messages['errorsavingcontact'] = 'Could not save the contact address';
$messages['movingmessage'] = 'Moving message...';
+$messages['receiptsent'] = 'Successfully send the receipt message';
+$messages['errorsendingreceipt'] = 'Could not send the receipt';
?> \ No newline at end of file
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 5131010af..36a3d7069 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -230,7 +230,7 @@ function rcmail_compose_headers($attrib)
function rcmail_compose_header_from($attrib)
{
- global $IMAP, $MESSAGE, $DB, $OUTPUT, $compose_mode;
+ global $IMAP, $MESSAGE, $DB, $USER, $OUTPUT, $compose_mode;
// pass the following attributes to the form class
$field_attrib = array('name' => '_from');
@@ -263,12 +263,7 @@ function rcmail_compose_header_from($attrib)
}
// get this user's identities
- $sql_result = $DB->query("SELECT identity_id, name, email, signature, html_signature
- FROM ".get_table_name('identities')."
- WHERE user_id=?
- AND del<>1
- ORDER BY ".$DB->quoteIdentifier('standard')." DESC, name ASC",
- $_SESSION['user_id']);
+ $sql_result = $USER->list_identities();
if ($DB->num_rows($sql_result))
{
@@ -869,7 +864,7 @@ $OUTPUT->add_handlers(array(
require_once('include/rcube_contacts.inc');
-$CONTACTS = new rcube_contacts($DB, $_SESSION['user_id']);
+$CONTACTS = new rcube_contacts($DB, $USER->ID);
$CONTACTS->set_pagesize(1000);
if ($result = $CONTACTS->list_records())
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index dd3801672..de8987248 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -21,6 +21,7 @@
require_once('lib/html2text.inc');
require_once('lib/enriched.inc');
+require_once('include/rcube_smtp.inc');
$EMAIL_ADDRESS_PATTERN = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i';
@@ -725,7 +726,7 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE)
// part text/[plain|html] OR message/delivery-status
else if (($primary_type=='text' && ($secondary_type=='plain' || $secondary_type=='html') && $mail_part->disposition!='attachment') ||
- ($primary_type=='message' && $secondary_type=='delivery-status'))
+ ($primary_type=='message' && ($secondary_type=='delivery-status' || $secondary_type=='disposition-notification')))
{
$mail_part->type = 'content';
$a_return_parts[] = $mail_part;
@@ -758,7 +759,7 @@ function rcmail_parse_message(&$structure, $arg=array(), $recursive=FALSE)
else
{
if (!$mail_part->filename)
- $mail_part->filename = 'file_'.$mail_part->mime_id;
+ $mail_part->filename = 'Part '.$mail_part->mime_id;
$a_attachments[] = $mail_part;
}
}
@@ -1250,6 +1251,67 @@ function rcmail_compose_cleanup()
unset($_SESSION['compose']);
}
+
+
+/**
+ * Send the given message compose object using the configured method
+ */
+function rcmail_deliver_message(&$message, $from, $mailto)
+{
+ global $CONFIG;
+
+ $headers = $message->headers();
+ $msg_body = $message->get();
+
+ // send thru SMTP server using custom SMTP library
+ if ($CONFIG['smtp_server'])
+ {
+ // generate list of recipients
+ $a_recipients = array($mailto);
+
+ if (strlen($headers['Cc']))
+ $a_recipients[] = $headers['Cc'];
+ if (strlen($headers['Bcc']))
+ $a_recipients[] = $headers['Bcc'];
+
+ // clean Bcc from header for recipients
+ $send_headers = $headers;
+ unset($send_headers['Bcc']);
+
+ // send message
+ $smtp_response = array();
+ $sent = smtp_mail($from, $a_recipients, ($foo = $message->txtHeaders($send_headers)), $msg_body, $smtp_response);
+
+ // log error
+ if (!$sent)
+ raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__,
+ 'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE);
+ }
+
+ // send mail using PHP's mail() function
+ else
+ {
+ // unset some headers because they will be added by the mail() function
+ $headers_enc = $message->headers($headers);
+ $headers_php = $message->_headers;
+ unset($headers_php['To'], $headers_php['Subject']);
+
+ // reset stored headers and overwrite
+ $message->_headers = array();
+ $header_str = $message->txtHeaders($headers_php);
+
+ if (ini_get('safe_mode'))
+ $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str);
+ else
+ $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from");
+ }
+
+
+ $message->_headers = array();
+ $message->headers($headers);
+
+ return $sent;
+}
// register UI objects
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index d118af53f..6f4744db9 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -22,7 +22,6 @@
//require_once('lib/smtp.inc');
-require_once('include/rcube_smtp.inc');
require_once('lib/html2text.inc');
require_once('lib/rc_mail_mime.inc');
@@ -37,26 +36,19 @@ if (!isset($_SESSION['compose']['id']))
/****** message sending functions ********/
+// get identity record
function rcmail_get_identity($id)
{
- global $DB, $OUTPUT;
+ global $USER, $OUTPUT;
- // get identity record
- $sql_result = $DB->query("SELECT *, email AS mailto
- FROM ".get_table_name('identities')."
- WHERE identity_id=?
- AND user_id=?
- AND del<>1",
- $id,$_SESSION['user_id']);
-
- if ($DB->num_rows($sql_result))
+ if ($sql_arr = $USER->get_identity($id))
{
- $sql_arr = $DB->fetch_assoc($sql_result);
$out = $sql_arr;
+ $out['mailto'] = $sql_arr['email'];
$name = strpos($sql_arr['name'], ",") ? '"'.$sql_arr['name'].'"' : $sql_arr['name'];
$out['string'] = sprintf('%s <%s>',
rcube_charset_convert($name, RCMAIL_CHARSET, $OUTPUT->get_charset()),
- $sql_arr['mailto']);
+ $sql_arr['email']);
return $out;
}
@@ -166,7 +158,7 @@ if (empty($identity_arr['string']))
$identity_arr['string'] = $from;
// compose headers array
-$headers = array('Date' => date('D, j M Y H:i:s O'),
+$headers = array('Date' => date('r'),
'From' => rcube_charset_convert($identity_arr['string'], RCMAIL_CHARSET, $message_charset),
'To' => $mailto);
@@ -225,23 +217,11 @@ $message_body = get_input_value('_message', RCUBE_INPUT_POST, TRUE, $message_cha
if (!$savedraft && !empty($CONFIG['generic_message_footer']) && ($footer = file_get_contents(realpath($CONFIG['generic_message_footer']))))
$message_body .= "\r\n" . rcube_charset_convert($footer, 'UTF-8', $message_charset);
-// try to autodetect operating system and use the correct line endings
-// use the configured delimiter for headers
-if (!empty($CONFIG['mail_header_delimiter']))
- $header_delm = $CONFIG['mail_header_delimiter'];
-else if (strtolower(substr(PHP_OS, 0, 3)=='win'))
- $header_delm = "\r\n";
-else if (strtolower(substr(PHP_OS, 0, 3)=='mac'))
- $header_delm = "\r\n";
-else
- $header_delm = "\n";
-
-
$isHtmlVal = strtolower(get_input_value('_is_html', RCUBE_INPUT_POST));
$isHtml = ($isHtmlVal == "1");
// create extended PEAR::Mail_mime instance
-$MAIL_MIME = new rc_mail_mime($header_delm);
+$MAIL_MIME = new rc_mail_mime(rcmail_header_delm());
// For HTML-formatted messages, construct the MIME message with both
// the HTML part and the plain-text part
@@ -282,80 +262,30 @@ $charset_7bit = array('ASCII', 'ISO-2022-JP', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8
$transfer_encoding = in_array(strtoupper($message_charset), $charset_7bit) ? '7bit' : '8bit';
// encoding settings for mail composing
-$message_param = array(
+$MAIL_MIME->setParam(array(
'text_encoding' => $transfer_encoding,
'html_encoding' => 'quoted-printable',
'head_encoding' => 'quoted-printable',
'head_charset' => $message_charset,
'html_charset' => $message_charset,
'text_charset' => $message_charset,
-);
-
-// compose message body and get headers
-$msg_body = $MAIL_MIME->get($message_param);
-// unset to save memory.
-unset($MAIL_MIME->_parts);
+));
// encoding subject header with mb_encode provides better results with asian characters
if ($MBSTRING && function_exists("mb_encode_mimeheader"))
{
mb_internal_encoding($message_charset);
- $mb_subject = mb_encode_mimeheader($headers['Subject'], $message_charset, 'Q');
+ $headers['Subject'] = mb_encode_mimeheader($headers['Subject'], $message_charset, 'Q');
mb_internal_encoding(RCMAIL_CHARSET);
}
-// Begin SMTP Delivery Block
-if (!$savedraft) {
+// pass headers to message object
+$MAIL_MIME->headers($headers);
- // send thru SMTP server using custom SMTP library
- if ($CONFIG['smtp_server'])
- {
- // generate list of recipients
- $a_recipients = array($mailto);
-
- if (strlen($headers['Cc']))
- $a_recipients[] = $headers['Cc'];
- if (strlen($headers['Bcc']))
- $a_recipients[] = $headers['Bcc'];
-
- // clean Bcc from header for recipients
- $send_headers = $headers;
- unset($send_headers['Bcc']);
-
- if (!empty($mb_subject))
- $send_headers['Subject'] = $mb_subject;
-
- // send message
- $smtp_response = array();
- $sent = smtp_mail($from, $a_recipients, ($foo = $MAIL_MIME->txtHeaders($send_headers)), $msg_body, $smtp_response);
-
- // log error
- if (!$sent)
- raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__,
- 'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE);
- }
-
- // send mail using PHP's mail() function
- else
- {
- // unset some headers because they will be added by the mail() function
- $headers_enc = $MAIL_MIME->headers($headers);
- $headers_php = $MAIL_MIME->_headers;
- unset($headers_php['To'], $headers_php['Subject']);
-
- if (!empty($mb_subject))
- $headers_enc['Subject'] = $mb_subject;
-
- // reset stored headers and overwrite
- $MAIL_MIME->_headers = array();
- $header_str = $MAIL_MIME->txtHeaders($headers_php);
-
- if (ini_get('safe_mode'))
- $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str);
- else
- $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from");
- }
-
+// Begin SMTP Delivery Block
+if (!$savedraft)
+{
+ $sent = rcmail_deliver_message($MAIL_MIME, $from, $mailto);
// return to compose page if sending failed
if (!$sent)
@@ -365,7 +295,6 @@ if (!$savedraft) {
return;
}
-
// set repliead flag
if ($_SESSION['compose']['reply_uid'])
$IMAP->set_flag($_SESSION['compose']['reply_uid'], 'ANSWERED');
@@ -382,21 +311,15 @@ else
if ($CONFIG[$store_target])
{
- // create string of complete message headers
- $header_str = $MAIL_MIME->txtHeaders($headers);
-
// check if mailbox exists
if (!in_array_nocase($CONFIG[$store_target], $IMAP->list_mailboxes()))
$store_folder = $IMAP->create_mailbox($CONFIG[$store_target], TRUE);
else
$store_folder = TRUE;
- // add headers to message body
- $msg_body = $header_str."\r\n".$msg_body;
-
// append message to sent box
if ($store_folder)
- $saved = $IMAP->save_message($CONFIG[$store_target], $msg_body);
+ $saved = $IMAP->save_message($CONFIG[$store_target], $MAIL_MIME->getMessage());
// raise error if saving failed
if (!$saved)
diff --git a/program/steps/mail/sendmdn.inc b/program/steps/mail/sendmdn.inc
new file mode 100644
index 000000000..0944e7602
--- /dev/null
+++ b/program/steps/mail/sendmdn.inc
@@ -0,0 +1,97 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | program/steps/mail/sendmdn.inc |
+ | |
+ | This file is part of the RoundCube Webmail client |
+ | Copyright (C) 2007, RoundCube Dev. - Switzerland |
+ | Licensed under the GNU GPL |
+ | |
+ | PURPOSE: |
+ | Send a message disposition notification for a specific mail |
+ | |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com> |
+ +-----------------------------------------------------------------------+
+
+ $Id: sendmail.inc 930 2007-11-25 17:34:19Z thomasb $
+
+*/
+
+require_once('lib/rc_mail_mime.inc');
+
+
+if (!empty($_POST['_uid']))
+ {
+ $MESSAGE = array('UID' => get_input_value('_uid', RCUBE_INPUT_POST));
+ $MESSAGE['headers'] = $IMAP->get_headers($MESSAGE['UID']);
+ $MESSAGE['subject'] = rcube_imap::decode_mime_string($MESSAGE['headers']->subject, $MESSAGE['headers']->charset);
+
+ if ($MESSAGE['headers']->mdn_to && !$MESSAGE['headers']->mdn_sent)
+ {
+ $identity = $USER->get_identity();
+ $sender = format_email_recipient($identity['email'], $identity['name']);
+ $recipient = array_shift($IMAP->decode_address_list($MESSAGE['headers']->mdn_to));
+ $mailto = $recipient['mailto'];
+
+ $COMPOSE = new rc_mail_mime(rcmail_header_delm());
+ $COMPOSE->setParam(array(
+ 'text_encoding' => 'quoted-printable',
+ 'html_encoding' => 'quoted-printable',
+ 'head_encoding' => 'quoted-printable',
+ 'head_charset' => RCMAIL_CHARSET,
+ 'html_charset' => RCMAIL_CHARSET,
+ 'text_charset' => RCMAIL_CHARSET,
+ ));
+
+ // compose headers array
+ $headers = array(
+ 'Date' => date('r'),
+ 'From' => $sender,
+ 'To' => $MESSAGE['headers']->mdn_to,
+ 'Subject' => rcube_label('receiptread') . ': ' . $MESSAGE['subject'],
+ 'Message-ID' => sprintf('<%s@%s>', md5(uniqid('rcmail'.rand(),true)), rcmail_mail_domain($_SESSION['imap_host'])),
+ 'X-Sender' => $identity['email'],
+ 'Content-Type' => 'multipart/report; report-type=disposition-notification',
+ );
+
+ if (!empty($CONFIG['useragent']))
+ $headers['User-Agent'] = $CONFIG['useragent'];
+
+ $body = rcube_label("yourmessage") . "\r\n\r\n" .
+ "\t" . rcube_label("to") . ': ' . rcube_imap::decode_mime_string($MESSAGE['headers']->to, $MESSAGE['headers']->charset) . "\r\n" .
+ "\t" . rcube_label("subject") . ': ' . $MESSAGE['subject'] . "\r\n" .
+ "\t" . rcube_label("sent") . ': ' . format_date(strtotime($MESSAGE['headers']->date), $CONFIG['date_long']) . "\r\n" .
+ "\r\n" . rcube_label("receiptnote") . "\r\n";
+
+ $report = "Reporting-UA: RoundCube Webmail (Version ".RCMAIL_VERSION.")\r\n";
+
+ if ($MESSAGE['headers']->to)
+ $report .= "Original-Recipient: {$MESSAGE['headers']->to}\r\n";
+
+ $report .= "Final-Recipient: rfc822; {$identity['email']}\r\n" .
+ "Original-Message-ID: {$MESSAGE['headers']->messageID}\r\n" .
+ "Disposition: manual-action/MDN-sent-manually; displayed\r\n";
+
+ $COMPOSE->headers($headers, true);
+ $COMPOSE->setTXTBody($body);
+ $COMPOSE->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline');
+
+ $sent = rcmail_deliver_message($COMPOSE, $identity['email'], $mailto);
+
+ if ($sent)
+ {
+ $IMAP->set_flag($MESSAGE['UID'], 'MDNSENT');
+ $OUTPUT->set_env('mdn_request', false);
+ $OUTPUT->show_message('receiptsent', 'confirmation');
+ $OUTPUT->send();
+ }
+ }
+}
+
+// Error if arrive here
+$OUTPUT->show_message('errorsendingreceipt', 'error');
+$OUTPUT->send();
+
+?> \ No newline at end of file
diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc
index 022edb0ed..45d64b87b 100644
--- a/program/steps/mail/show.inc
+++ b/program/steps/mail/show.inc
@@ -75,7 +75,10 @@ if ($_GET['_uid'])
// check for unset disposition notification
if ($MESSAGE['headers']->mdn_to && !$MESSAGE['headers']->mdn_sent)
+ {
+ rcube_add_label('mdnrequest');
$OUTPUT->set_env('mdn_request', true);
+ }
$next = $prev = -1;
// get previous, first, next and last message UID
diff --git a/program/steps/settings/delete_identity.inc b/program/steps/settings/delete_identity.inc
index 3614a3e96..06fdd94f4 100644
--- a/program/steps/settings/delete_identity.inc
+++ b/program/steps/settings/delete_identity.inc
@@ -21,15 +21,8 @@
if (($ids = get_input_value('_iid', RCUBE_INPUT_GET)) && preg_match('/^[0-9]+(,[0-9]+)*$/', $ids))
{
- $DB->query(
- "UPDATE ".get_table_name('identities')."
- SET del=1
- WHERE user_id=?
- AND identity_id IN (".$ids.")",
- $_SESSION['user_id']);
-
- $count = $DB->affected_rows();
- if ($count)
+
+ if ($USER->delete_identity($ids))
$OUTPUT->show_message('deletedsuccessfully', 'confirmation');
// send response
diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc
index 51a0cd0a0..4d89f7cbc 100644
--- a/program/steps/settings/edit_identity.inc
+++ b/program/steps/settings/edit_identity.inc
@@ -21,14 +21,7 @@
if (($_GET['_iid'] || $_POST['_iid']) && $_action=='edit-identity')
{
- $DB->query("SELECT * FROM ".get_table_name('identities')."
- WHERE identity_id=?
- AND user_id=?
- AND del<>1",
- get_input_value('_iid', RCUBE_INPUT_GPC),
- $_SESSION['user_id']);
-
- $IDENTITY_RECORD = $DB->fetch_assoc();
+ $IDENTITY_RECORD = $USER->get_identity(get_input_value('_iid', RCUBE_INPUT_GPC));
if (is_array($IDENTITY_RECORD))
$OUTPUT->set_env('iid', $IDENTITY_RECORD['identity_id']);
diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc
index ecdbcbd76..e63f01620 100644
--- a/program/steps/settings/func.inc
+++ b/program/steps/settings/func.inc
@@ -20,15 +20,8 @@
*/
-// get user record
-$sql_result = $DB->query("SELECT username, mail_host FROM ".get_table_name('users')."
- WHERE user_id=?",
- $_SESSION['user_id']);
-
-if ($USER_DATA = $DB->fetch_assoc($sql_result))
-{
- $OUTPUT->set_pagetitle(rcube_label('settingsfor') . " ". $USER_DATA['username'] . (!strpos($USER_DATA['username'], '@') ? '@'.$USER_DATA['mail_host'] : ''));
-}
+if ($USER->ID)
+ $OUTPUT->set_pagetitle(rcube_label('settingsfor') . " ". $USER->get_username());
@@ -204,16 +197,7 @@ function rcmail_user_prefs_form($attrib)
function rcmail_identities_list($attrib)
{
- global $DB, $CONFIG, $OUTPUT;
-
-
- // get contacts from DB
- $sql_result = $DB->query("SELECT * FROM ".get_table_name('identities')."
- WHERE del<>1
- AND user_id=?
- ORDER BY standard DESC, name ASC",
- $_SESSION['user_id']);
-
+ global $OUTPUT, $USER;
// add id to message list table if not specified
if (!strlen($attrib['id']))
@@ -223,7 +207,7 @@ function rcmail_identities_list($attrib)
$a_show_cols = array('name', 'email', 'organization', 'reply-to');
// create XHTML table
- $out = rcube_table_output($attrib, $sql_result, $a_show_cols, 'identity_id');
+ $out = rcube_table_output($attrib, $USER->list_identities(), $a_show_cols, 'identity_id');
// set client env
$OUTPUT->add_gui_object('identitieslist', $attrib['id']);
diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc
index 8079b589a..2c2a55e49 100644
--- a/program/steps/settings/save_identity.inc
+++ b/program/steps/settings/save_identity.inc
@@ -33,123 +33,78 @@ if (empty($_POST['_name']) || empty($_POST['_email']))
}
+$save_data = array();
+foreach ($a_save_cols as $col)
+{
+ $fname = '_'.$col;
+ if (isset($_POST[$fname]))
+ $save_data[$col] = get_input_value($fname, RCUBE_INPUT_POST, in_array($col, $a_html_cols));
+}
+
+// set "off" values for checkboxes that were not checked, and therefore
+// not included in the POST body.
+foreach ($a_boolean_cols as $col)
+{
+ $fname = '_' . $col;
+ if (!isset($_POST[$fname]))
+ $save_data[$col] = 0;
+}
+
+
// update an existing contact
if ($_POST['_iid'])
+{
+ if ($updated = $USER->update_identity(get_input_value('_iid', RCUBE_INPUT_POST), $save_data))
{
- $a_write_sql = array();
-
- foreach ($a_save_cols as $col)
- {
- $fname = '_'.$col;
- if (isset($_POST[$fname]))
- $a_write_sql[] = sprintf("%s=%s",
- $DB->quoteIdentifier($col),
- $DB->quote(get_input_value($fname, RCUBE_INPUT_POST, in_array($col, $a_html_cols))));
- }
-
- // set "off" values for checkboxes that were not checked, and therefore
- // not included in the POST body.
- foreach ($a_boolean_cols as $col)
- {
- $fname = '_' . $col;
- if (!isset($_POST[$fname]))
- $a_write_sql[] = sprintf("%s=0", $DB->quoteIdentifier($col));
- }
-
- if (sizeof($a_write_sql))
- {
- $DB->query(
- "UPDATE ".get_table_name('identities')."
- SET ".join(', ', $a_write_sql)."
- WHERE identity_id=?
- AND user_id=?
- AND del<>1",
- get_input_value('_iid', RCUBE_INPUT_POST),
- $_SESSION['user_id']);
-
- $updated = $DB->affected_rows();
- }
-
- if ($updated)
- {
$OUTPUT->show_message('successfullysaved', 'confirmation');
if (!empty($_POST['_standard']))
$default_id = get_input_value('_iid', RCUBE_INPUT_POST);
if ($_POST['_framed'])
- {
+ {
// update the changed col in list
// ...
- }
}
+ }
else if ($DB->is_error())
- {
+ {
// show error message
$OUTPUT->show_message('errorsaving', 'error');
rcmail_overwrite_action('edit-identitiy');
return;
- }
}
+}
// insert a new contact
else
+{
+ if ($insert_id = $USER->insert_identity($save_data))
{
- $a_insert_cols = $a_insert_values = array();
-
- foreach ($a_save_cols as $col)
- {
- $fname = '_'.$col;
- if (!isset($_POST[$fname]))
- continue;
-
- $a_insert_cols[] = $DB->quoteIdentifier($col);
- $a_insert_values[] = $DB->quote(get_input_value($fname, RCUBE_INPUT_POST, in_array($col, $a_html_cols)));
- }
-
- if (sizeof($a_insert_cols))
- {
- $DB->query("INSERT INTO ".get_table_name('identities')."
- (user_id, ".join(', ', $a_insert_cols).")
- VALUES (?, ".join(', ', $a_insert_values).")",
- $_SESSION['user_id']);
-
- $insert_id = $DB->insert_id(get_sequence_name('identities'));
- }
-
- if ($insert_id)
- {
$_GET['_iid'] = $insert_id;
if (!empty($_POST['_standard']))
$default_id = $insert_id;
if ($_POST['_framed'])
- {
+ {
// add contact row or jump to the page where it should appear
// ....
- }
}
+ }
else
- {
+ {
// show error message
$OUTPUT->show_message('errorsaving', 'error');
rcmail_overwrite_action('edit-identity');
return;
- }
}
+}
// mark all other identities as 'not-default'
if ($default_id)
- $DB->query(
- "UPDATE ".get_table_name('identities')."
- SET ".$DB->quoteIdentifier('standard')."='0'
- WHERE user_id=?
- AND identity_id<>?
- AND del<>1",
- $_SESSION['user_id'],
- $default_id);
+ $USER->set_default($default_id);
// go to next step
rcmail_overwrite_action($_framed ? 'edit-identity' : 'identities');
diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc
index 0565260f0..caa4a49e5 100644
--- a/program/steps/settings/save_prefs.inc
+++ b/program/steps/settings/save_prefs.inc
@@ -44,15 +44,12 @@ if (isset($_POST['_language']))
// force min size
if ($a_user_prefs['pagesize'] < 1)
- {
$a_user_prefs['pagesize'] = 10;
- }
+
if (isset($CONFIG['max_pagesize']) && ($a_user_prefs['pagesize'] > $CONFIG['max_pagesize']))
- {
$a_user_prefs['pagesize'] = (int) $CONFIG['max_pagesize'];
- }
-if (rcmail_save_user_prefs($a_user_prefs))
+if ($USER->save_prefs($a_user_prefs))
$OUTPUT->show_message('successfullysaved', 'confirmation');
diff --git a/skins/default/mail.css b/skins/default/mail.css
index fb130ce6c..6e44c17d7 100644
--- a/skins/default/mail.css
+++ b/skins/default/mail.css
@@ -632,16 +632,20 @@ table.headers-table tr td.subject
{
position:relative;
min-height: 300px;
- padding-top: 10px;
padding-bottom: 10px;
background-color: #FFFFFF;
}
div.message-part
{
- padding: 8px;
- padding-top: 10px;
- overflow: hidden;
+ padding: 10px 8px;
+ border-top: 1px solid #ccc;
+/* overflow: hidden; */
+}
+
+#messagebody div:first-child
+{
+ border-top: 0;
}
div.message-part a