-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathautomatic_addressbook.php
executable file
·321 lines (285 loc) · 13.4 KB
/
automatic_addressbook.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Automatic address book
*
*
* Simple plugin to register to "collect" all recipients of sent mail
* to a dedicated address book (usefull for autocompleting email you
* already used). User can choose in preferences (compose group) to
* enable or disable the feature of this plugin.
* Aims to reproduce the similar features of thunderbird or gmail.
*
* @version 0.4
* @author Jocelyn Delalande (slightly modified by Roland 'rosali' Liebl)
* @author Sebastien Blaisot <[email protected]>
* @website https://github.com/sblaisot/automatic_addressbook
* @licence http://www.gnu.org/licenses/gpl-3.0.html GNU GPLv3+
*
*/
/*
* Skeletton based on "example_addressbook" plugin.
* Contact adding code inspired by addcontact.inc by Thomas Bruederli
*/
class automatic_addressbook extends rcube_plugin
{
public $task = 'mail|addressbook|settings';
private $abook_id = 'collected';
/**
* Initialize plugin
*/
public function init()
{
$this->add_hook('addressbooks_list', array($this, 'address_sources'));
$this->add_hook('addressbook_get', array($this, 'get_address_book'));
$this->add_hook('message_sent', array($this, 'register_recipients'));
$this->add_hook('preferences_list', array($this, 'settings_table'));
$this->add_hook('preferences_save', array($this, 'save_prefs'));
$this->add_hook('contact_update', array($this, 'handle_doubles'));
$this->add_hook('contact_create', array($this, 'handle_doubles'));
$this->add_texts('localization/', false);
$this->load_config('config/config.inc.php.dist');
if (file_exists("./plugins/automatic_addressbook/config/config.inc.php")) {
$this->load_config('config/config.inc.php');
}
// Adds an address-book category in rc <= 0.5, retro-compatibility code,
// not needed for rc 0.6
$this->add_hook('preferences_sections_list', array($this, 'add_addressbook_category'));
// use this address book for autocompletion queries
$config = rcmail::get_instance()->config;
$sources = $config->get('autocomplete_addressbooks', array('sql'));
if (!in_array($this->abook_id, $sources) &&
$config->get('use_auto_abook', true) &&
$config->get('use_auto_abook_for_completion', true)) {
$sources[] = $this->abook_id;
$config->set('autocomplete_addressbooks', $sources);
}
}
/**
* Register automatic_addressbook as address source
*
* @param array $p Hash array with list of available address books
* @return array $p Hash array with list of available address books
*/
public function address_sources($p)
{
$rcmail = rcmail::get_instance();
if ($rcmail->config->get('use_auto_abook', true)) {
$p['sources'][$this->abook_id] =
array('id' => $this->abook_id,
'name' => rcube_utils::rep_specialchars_output($this->gettext('automaticallycollected')),
'readonly' => FALSE, 'groups' => false);
}
return $p;
}
/**
* Requests automatic_addressbook instance
*
* @param array $p Hash array containing the id of the requested abook
* @return array $p Hash array containing instance of the requested abook
*/
public function get_address_book($p)
{
$rcmail = rcmail::get_instance();
if (($p['id'] === $this->abook_id) && $rcmail->config->get('use_auto_abook', true)) {
require_once dirname(__FILE__) . '/automatic_addressbook_backend.php';
$p['instance'] = new automatic_addressbook_backend($rcmail->db, $rcmail->user->ID);
$p['instance']->groups = false;
}
return $p;
}
/**
* Collect the email address of a just-sent email recipients into
* the automatic addressbook (if it's not already in another
* addressbook).
*
* @param array $p Hash array containing header and body of sent mail
* @return nothing
*/
public function register_recipients($p)
{
$rcmail = rcmail::get_instance();
if (!$rcmail->config->get('use_auto_abook', true)) {
return;
}
$headers = $p['headers'];
if (!class_exists('rcube_mime')) { // RC < 0.8 compatibility code
$IMAP = new rcube_imap(null);
$all_recipients = array_merge(
$IMAP->decode_address_list($headers['To'], null, true, $headers['charset']),
$IMAP->decode_address_list($headers['Cc'], null, true, $headers['charset']),
$IMAP->decode_address_list($headers['Bcc'], null, true, $headers['charset'])
);
} else {
$all_recipients = array_merge(
rcube_mime::decode_address_list($headers['To'], null, true, $headers['charset']),
rcube_mime::decode_address_list($headers['Cc'], null, true, $headers['charset']),
rcube_mime::decode_address_list($headers['Bcc'], null, true, $headers['charset'])
);
}
require_once dirname(__FILE__) . '/automatic_addressbook_backend.php';
$CONTACTS = new automatic_addressbook_backend($rcmail->db, $rcmail->user->ID);
foreach ($all_recipients as $recipient) {
// Bcc and Cc can be empty
if ($recipient['mailto'] != '') {
$contact = array(
'email' => $recipient['mailto'],
'name' => $recipient['name']
);
// use email address part for name
if (empty($contact['name']) || $contact['name'] == $contact['email']) {
$contact['name'] = ucfirst(preg_replace('/[\.\-]/', ' ',
substr($contact['email'], 0, strpos($contact['email'], '@'))));
}
/* We only want to add the contact to the collected contacts
* address book if it is not already in an addressbook, so we
* first lookup in every address source.
*/
$book_types = (array)$rcmail->config->get('autocomplete_addressbooks', 'sql');
foreach ($book_types as $id) {
$abook = $rcmail->get_address_book($id);
$previous_entries = $abook->search('email', $contact['email'], false, false);
if ($previous_entries->count) {
break;
}
}
if (!$previous_entries->count) {
$plugin = $rcmail->plugins->exec_hook('contact_create', array('record' => $contact,
'source' => $this->abook_id));
if (!$plugin['abort']) {
$CONTACTS->insert($contact, false);
}
}
}
}
}
/**
* Adds an address-book settings category in rc <= 0.5, not needed for rc >= 0.6
*
* @param array $args Hash array with list (hash array) of sections and list (hash array) of sections
* @return array Hash array with list (hash array) of sections and list (hash array) of sections
*/
public function add_addressbook_category($args)
{
$temp = $args['list']['server'];
unset($args['list']['server']);
$args['list']['addressbook']['id'] = 'addressbook';
$args['list']['addressbook']['section'] = $this->gettext('addressbook');
$args['list']['server'] = $temp;
return $args;
}
/**
* Adds a check-box to enable/disable automatic address collection.
*
* @param array $args Hash array containing section and preference blocks
* @return array Hash array containing preference blocks with addressbook preferences
*/
public function settings_table($args)
{
if ($args['section'] == 'addressbook') {
$use_auto_abook = rcmail::get_instance()->config->get('use_auto_abook', true);
$field_id = 'rcmfd_use_auto_abook';
$checkbox = new html_checkbox(array(
'name' => '_use_auto_abook',
'id' => $field_id, 'value' => 1
));
$args['blocks']['automaticallycollected']['name'] = $this->gettext('automaticallycollected');
$args['blocks']['automaticallycollected']['options']['use_subscriptions'] = array(
'title' => html::label($field_id, rcube_utils::rep_specialchars_output($this->gettext('useautoabook'))),
'content' => $checkbox->show($use_auto_abook ? 1 : 0),
);
$use_auto_abook_for_completion = rcmail::get_instance()->config->get('use_auto_abook_for_completion', true);
$field_id2 = 'rcmfd_use_auto_abook_for_completion';
$checkbox2 = new html_checkbox(array(
'name' => '_use_auto_abook_for_completion',
'id' => $field_id2, 'value' => 1
));
$args['blocks']['automaticallycollected']['name'] = $this->gettext('automaticallycollected');
$args['blocks']['automaticallycollected']['options']['use_autocompletion'] = array(
'title' => html::label($field_id2, rcube_utils::rep_specialchars_output($this->gettext('useforcompletion'))),
'content' => $checkbox2->show($use_auto_abook_for_completion ? 1 : 0),
);
}
return $args;
}
/**
* Save preferences
*
* @param array $args Hash array with prefs to be saved
* @return array $args Hash array with result: boolean, abort: boolean, prefs: array
*/
public function save_prefs($args)
{
if ($args['section'] == 'addressbook') {
$rcmail = rcmail::get_instance();
$use_auto_abook = $rcmail->config->get('use_auto_abook');
$args['prefs']['use_auto_abook'] = isset($_POST['_use_auto_abook']) ? true : false;
$use_auto_abook_for_completion = $rcmail->config->get('use_auto_abook_for_completion');
$args['prefs']['use_auto_abook_for_completion'] = isset($_POST['_use_auto_abook_for_completion']) ? true : false;
}
return $args;
}
/**
* When a contact is added to a "regular" addressbook, take care to
* delete it from collected addressbook if it was in.
*
* @param array $args Hash array with contact details
* @return array record updated or abort
*/
public function handle_doubles($args)
{
$rcmail = rcmail::get_instance();
if (!$rcmail->config->get('use_auto_abook', true)) {
return $args;
}
$moveto = $rcmail->config->get('on_edit_move_to_default');
if ($args['source'] == $this->abook_id && !empty($args['id']) && $moveto) {
$args['source'] = $rcmail->config->get('default_addressbook');
$plugin = $rcmail->plugins->exec_hook('contact_create', array('record' => $args['record'],
'source' => $args['source']));
if (!$plugin['abort']) {
$CONTACTS = $rcmail->get_address_book($args['source']);
$insert_id = $CONTACTS->insert($args['record'], false);
} else {
$insert_id = $plugin['result'];
}
$rcmail->output->show_message('automatic_addressbook.contactmoved', 'confirmation');
$rcmail->output->command('parent.list_contacts');
return array('abort' => true, 'result' => $insert_id);
}
if ($args['source'] !== $this->abook_id) {
foreach (array('email:home', 'email:work', 'email:other') as $email_field) {
// Would trigger a warning with rc 0.5 without this if
if ($args['record'][$email_field]) {
foreach ($args['record'][$email_field] as $email) {
$contact_emails[] = $email;
}
}
}
// rc <= 0.5, retro-compatibility code, not needed for rc 0.6
$contact_emails[] = $args['record']['email'];
//
foreach ($contact_emails as $contact_email) {
if (!empty($contact_email)) {
$auto_abook = $rcmail->get_address_book($this->abook_id);
$auto_abook->reset();
$collected_contact = $auto_abook->search('email', $contact_email, false, true);
while ($record = $collected_contact->iterate()) {
$plugin = $rcmail->plugins->exec_hook('contact_delete', array('id' => $record['contact_id'],
'source' => $this->abook_id));
if (!$plugin['abort']) {
$auto_abook->delete($record['contact_id']);
$rcmail->output->show_message('automatic_addressbook.contactremoved', 'confirmation');
}
}
}
}
if ($rcmail->task == "addressbook" &&
$rcmail->action == "copy" &&
$_REQUEST['_source'] == $this->abook_id) {
$rcmail->output->command('parent.list_contacts');
}
}
return $args;
}
}