diff options
author | Aleksander Machniak <alec@alec.pl> | 2020-09-20 11:00:08 +0300 |
---|---|---|
committer | Aleksander Machniak <alec@alec.pl> | 2020-09-20 11:00:08 +0300 |
commit | 9713ce364cd14e40edec1de819e17341a6745c71 (patch) | |
tree | 72c77b70ed9b96c39e0084ef255c75bf175af2b5 /program/include/rcmail.php | |
parent | 86849a0ee4c10b3a866b0161a2572aa8d9e7a461 (diff) |
Automatically collected recipients and trusted senders (#6904)
Added configurable Collected Recipients addressbook source (#4971)
Added configurable Trusted Senders addressbook source (#5046)
Added 'contact_exists' hook
Diffstat (limited to 'program/include/rcmail.php')
-rw-r--r-- | program/include/rcmail.php | 163 |
1 files changed, 143 insertions, 20 deletions
diff --git a/program/include/rcmail.php b/program/include/rcmail.php index b983f3ac8..89090dbbf 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -208,7 +208,9 @@ class rcmail extends rcube /** * Return instance of the internal address book class * - * @param string $id Address book identifier (-1 for default addressbook) + * @param string $id Address book identifier. It accepts also special values: + * - rcube_addressbook::TYPE_CONTACT (or 'sql') for the SQL addressbook + * - rcube_addressbook::TYPE_DEFAULT for the default addressbook * @param boolean $writeable True if the address book needs to be writeable * * @return rcube_contacts Address book object @@ -221,13 +223,15 @@ class rcmail extends rcube // 'sql' is the alias for '0' used by autocomplete if ($id == 'sql') { - $id = '0'; + $id = rcube_addressbook::TYPE_CONTACT; } - else if ($id == -1) { + else if ($id == rcube_addressbook::TYPE_DEFAULT || $id == -1) { // -1 for BC $id = $this->config->get('default_addressbook'); $default = true; } + $id = (string) $id; + // use existing instance if (isset($this->address_books[$id]) && ($this->address_books[$id] instanceof rcube_addressbook)) { $contacts = $this->address_books[$id]; @@ -236,9 +240,12 @@ class rcmail extends rcube $domain = $this->config->mail_domain($_SESSION['storage_host']); $contacts = new rcube_ldap($ldap_config[$id], $this->config->get('ldap_debug'), $domain); } - else if ($id === '0') { + else if ($id === (string) rcube_addressbook::TYPE_CONTACT) { $contacts = new rcube_contacts($this->db, $this->get_user_id()); } + else if ($id === (string) rcube_addressbook::TYPE_RECIPIENT || $id === (string) rcube_addressbook::TYPE_TRUSTED_SENDER) { + $contacts = new rcube_addresses($this->db, $this->get_user_id(), (int) $id); + } else { $plugin = $this->plugins->exec_hook('addressbook_get', array('id' => $id, 'writeable' => $writeable)); @@ -325,22 +332,16 @@ class rcmail extends rcube { $abook_type = strtolower((string) $this->config->get('address_book_type', 'sql')); $ldap_config = (array) $this->config->get('ldap_public'); - $autocomplete = (array) $this->config->get('autocomplete_addressbooks'); $list = array(); // SQL-based (built-in) address book if ($abook_type === 'sql') { - if (!isset($this->address_books['0'])) { - $this->address_books['0'] = new rcube_contacts($this->db, $this->get_user_id()); - } - - $list['0'] = array( - 'id' => '0', + $list[rcube_addressbook::TYPE_CONTACT] = array( + 'id' => (string) rcube_addressbook::TYPE_CONTACT, 'name' => $this->gettext('personaladrbook'), - 'groups' => $this->address_books['0']->groups, - 'readonly' => $this->address_books['0']->readonly, - 'undelete' => $this->address_books['0']->undelete && $this->config->get('undo_timeout'), - 'autocomplete' => in_array_nocase('sql', $autocomplete), + 'groups' => true, + 'readonly' => false, + 'undelete' => $this->config->get('undo_timeout') > 0, ); } @@ -358,20 +359,40 @@ class rcmail extends rcube 'groups' => !empty($prop['groups']) || !empty($prop['group_filters']), 'readonly' => !$prop['writable'], 'hidden' => $prop['hidden'], - 'autocomplete' => in_array($id, $autocomplete) ); } } + $collected_recipients = $this->config->get('collected_recipients'); + $collected_senders = $this->config->get('collected_senders'); + + if ($collected_recipients === (string) rcube_addressbook::TYPE_RECIPIENT) { + $list[rcube_addressbook::TYPE_RECIPIENT] = array( + 'id' => (string) rcube_addressbook::TYPE_RECIPIENT, + 'name' => $this->gettext('collectedrecipients'), + 'groups' => false, + 'readonly' => true, + 'undelete' => false, + 'deletable' => true, + ); + } + + if ($collected_senders === (string) rcube_addressbook::TYPE_TRUSTED_SENDER) { + $list[rcube_addressbook::TYPE_TRUSTED_SENDER] = array( + 'id' => (string) rcube_addressbook::TYPE_TRUSTED_SENDER, + 'name' => $this->gettext('trustedsenders'), + 'groups' => false, + 'readonly' => true, + 'undelete' => false, + 'deletable' => true, + ); + } + // Plugins can also add address books, or re-order the list $plugin = $this->plugins->exec_hook('addressbooks_list', array('sources' => $list)); $list = $plugin['sources']; foreach ($list as $idx => $item) { - // register source for shutdown function - if (!is_object($this->address_books[$item['id']])) { - $this->address_books[$item['id']] = $item; - } // remove from list if not writeable as requested if ($writeable && $item['readonly']) { unset($list[$idx]); @@ -1170,6 +1191,108 @@ class rcmail extends rcube } /** + * Insert a contact to specified addressbook. + * + * @param array $contact Contact data + * @param rcube_addressbook $source The addressbook object + * @param string $error Filled with an error message/label on error + * + * @return int|bool Contact ID on success, False otherwise + */ + public function contact_create($contact, $source, &$error = null) + { + $contact['email'] = rcube_utils::idn_to_utf8($contact['email']); + + $contact = $this->plugins->exec_hook('contact_displayname', $contact); + + if (empty($contact['name'])) { + $contact['name'] = rcube_addressbook::compose_display_name($contact); + } + + // validate the contact + if (!$source->validate($contact, true)) { + $error = $source->get_error(); + return false; + } + + $plugin = $this->plugins->exec_hook('contact_create', array( + 'record' => $contact, + 'source' => $this->get_address_book_id($source), + )); + + $contact = $plugin['record']; + + if (!empty($plugin['abort'])) { + $error = $plugin['message']; + return $plugin['result']; + } + + return $source->insert($contact); + } + + /** + * Find an email address in user addressbook(s) + * + * @param string $email Email address + * @param int $type Addressbook type (see rcube_addressbook::TYPE_* consts) + * + * @return bool True if the address exists in specified addressbook(s), False otherwise + */ + public function contact_exists($email, $type) + { + if (empty($email) || !is_string($email) || !strpos($email, '@')) { + return false; + } + + // TODO: Consider using all writeable addressbooks by default + // TODO: Support TYPE_DEFAULT, TYPE_WRITEABLE, TYPE_READONLY filter + + if ($default = $this->get_address_book(rcube_addressbook::TYPE_DEFAULT, true)) { + $sources = array($this->get_address_book_id($default)); + } + + if ($type & rcube_addressbook::TYPE_RECIPIENT) { + $collected_recipients = $this->config->get('collected_recipients'); + if (strlen($collected_recipients) && !in_array($collected_recipients, $sources)) { + array_unshift($sources, $collected_recipients); + } + } + + if ($type & rcube_addressbook::TYPE_TRUSTED_SENDER) { + $collected_senders = $this->config->get('collected_senders'); + if (strlen($collected_senders) && !in_array($collected_senders, $sources)) { + array_unshift($sources, $collected_senders); + } + } + + $plugin = $this->plugins->exec_hook('contact_exists', array( + 'email' => $email, + 'type' => $type, + 'sources' => $sources, + )); + + if (!empty($plugin['abort'])) { + return $plugin['result']; + } + + foreach ($plugin['sources'] as $source) { + $contacts = $this->get_address_book($source); + + if (!$contacts) { + continue; + } + + $result = $contacts->search('email', $email, rcube_addressbook::SEARCH_STRICT, false); + + if ($result->count) { + return true; + } + } + + return false; + } + + /** * Returns RFC2822 formatted current date in user's timezone * * @return string Date |