This repository has been archived by the owner on Dec 27, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 60
/
Cyrus.php
335 lines (283 loc) · 12.4 KB
/
Cyrus.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
322
323
324
325
326
327
328
329
330
331
332
333
334
335
<?php
/**
* Tine 2.0
*
* @package Tinebase
* @subpackage User
* @license http://www.gnu.org/licenses/agpl.html AGPL Version 3
* @copyright Copyright (c) 2010-2015 Metaways Infosystems GmbH (http://www.metaways.de)
* @author Philipp Schüle <p.schuele@metaways.de>
*/
/**
* class Tinebase_EmailUser_Imap_Cyrus
*
* Email User Settings Managing for cyrus attributes
*
* @package Tinebase
* @subpackage User
* @todo add quota support
*/
class Tinebase_EmailUser_Imap_Cyrus extends Tinebase_User_Plugin_SqlAbstract implements Tinebase_EmailUser_Imap_Interface
{
/**
*
* @var Zend_Mail_Protocol_Imap
*/
protected $_imap;
/**
* email user config
*
* @var array
*/
protected $_config = array(
'domain' => null,
'host' => null,
'port' => 143,
'ssl' => FALSE,
'admin' => null,
'password' => null
);
/**
* the constructor
*
* @param array $_options
*/
public function __construct(array $_options = array())
{
// get cyrus imap config options (host, username, password, port)
$imapConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::IMAP, new Tinebase_Config_Struct())->toArray();
// merge _config and dovecot imap
$this->_config = array_merge($this->_config, $imapConfig['cyrus']);
// set domain from imap config
$this->_config['domain'] = !empty($imapConfig['domain']) ? $imapConfig['domain'] : null;
$this->_config['host'] = $imapConfig['host'];
$this->_config['port'] = !empty($imapConfig['port']) ? $imapConfig['port'] : 143;
$this->_config['ssl'] = $imapConfig['ssl'] != 'none' ? strtoupper($imapConfig['ssl']) : false;
if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__
. ' cyrus imap config: ' . print_r($this->_config, true));
}
/**
* get new email user
*
* @param Tinebase_Model_FullUser $_user
* @return Tinebase_Model_EmailUser
*/
public function getNewUser(Tinebase_Model_FullUser $_user)
{
$result = new Tinebase_Model_EmailUser(array(
'emailUserId' => $this->_appendDomain($_user->accountLoginName),
'emailUsername' => $this->_appendDomain($_user->accountLoginName)
));
return $result;
}
/**
* delete user by id
*
* @param Tinebase_Model_FullUser $_user
*/
public function inspectDeleteUser(Tinebase_Model_FullUser $_user)
{
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Delete Cyrus imap account of user ' . $_user->accountLoginName);
$imap = $this->_getImapConnection();
$mailboxString = $this->_getUserMailbox($_user->accountLoginName);
$mailboxes = $imap->listMailbox('', $mailboxString);
if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " search for {$mailboxString} in " . print_r($mailboxes, true));
// does mailbox exist at all?
if ((isset($mailboxes[$mailboxString]) || array_key_exists($mailboxString, $mailboxes))) {
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' must delete mailbox ');
if ($imap->setACL($mailboxString, $this->_config['admin'], 'lrswipcda') === true) {
$imap->delete($mailboxString);
}
}
}
/**
* inspect get user by property
*
* @param Tinebase_Model_User $_user the user object
*/
public function inspectGetUserByProperty(Tinebase_Model_User $_user)
{
if (! $_user instanceof Tinebase_Model_FullUser) {
return;
}
try {
$imap = $this->_getImapConnection();
} catch (Exception $e) {
if (Tinebase_Core::isLogLevel(Zend_Log::ERR)) Tinebase_Core::getLogger()->err(__METHOD__ . '::' . __LINE__
. ' Could not establish IMAP connection');
Tinebase_Exception::log($e);
return;
}
$mailboxString = $this->_getUserMailbox($_user->accountLoginName);
$quota = $this->_adminGetQuota($imap, $mailboxString);
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
. ' Got quota: ' . print_r($quota, TRUE));
$emailUser = new Tinebase_Model_EmailUser(array(
'emailUsername' => $this->_appendDomain($_user->accountLoginName),
'emailUserId' => $this->_appendDomain($_user->accountLoginName),
'emailMailQuota' => isset($quota['STORAGE']) ? round($quota['STORAGE']['limit'] * 1024) : null,
'emailMailSize' => isset($quota['STORAGE']) ? round($quota['STORAGE']['usage'] * 1024) : null,
'emailHost' => $this->_config['host'],
'emailPort' => $this->_config['port'],
'emailSecure' => $this->_config['ssl'],
));
$_user->imapUser = $emailUser;
$_user->emailUser = Tinebase_EmailUser::merge(clone $_user->imapUser, isset($_user->emailUser) ? $_user->emailUser : null);
}
/**
* update/set email user password
*
* @param string $_userId
* @param string $_password
* @param bool $_encrypt
* @param bool $_mustChange
* @param array $_additionalData
* @return void
*/
public function inspectSetPassword($_userId, string $_password, bool $_encrypt = true, bool $_mustChange = false, array &$_additionalData = [])
{
// nothing to be done for cyrus imap server
}
/**
* adds email properties for a new user
*
* @param Tinebase_Model_FullUser $_addedUser
* @param Tinebase_Model_FullUser $_newUserProperties
*/
protected function _addUser(Tinebase_Model_FullUser $_addedUser, Tinebase_Model_FullUser $_newUserProperties)
{
// do nothing when no email address is set
if (empty($_addedUser->accountEmailAddress)) {
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ .
" user {$_addedUser->accountLoginName} has no email address. Don't create cyrus imap mailbox."
);
return;
}
$imap = $this->_getImapConnection();
$mailboxString = $this->_getUserMailbox($_addedUser->accountLoginName);
$mailboxes = $imap->listMailbox('', $mailboxString);
if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " search for {$mailboxString} in " . print_r($mailboxes, true));
if (!(isset($mailboxes[$mailboxString]) || array_key_exists($mailboxString, $mailboxes))) {
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' must create mailbox: '. $mailboxString);
if ($imap->create($mailboxString) == true) {
if ($imap->setACL($mailboxString, $this->_appendDomain($_addedUser->accountLoginName), 'lrswipcda') !== true) {
// failed to set acl
}
}
}
$this->_setImapQuota($_newUserProperties, $imap, $mailboxString);
$this->inspectGetUserByProperty($_addedUser);
}
/**
* set quota directly on IMAP server
*
* @param Tinebase_Model_FullUser $_user
* @param Zend_Mail_Protocol_Imap $_imap
* @param string $_mailboxString
*/
protected function _setImapQuota(Tinebase_Model_FullUser $_user, Zend_Mail_Protocol_Imap $_imap = NULL, $_mailboxString = NULL)
{
$imap = ($_imap !== NULL) ? $_imap : $this->_getImapConnection();
$mailboxString = ($_mailboxString !== NULL) ? $_mailboxString : $this->_getUserMailbox($_user->accountLoginName);
if (isset($_user->imapUser)) {
$limit = ($_user->imapUser->emailMailQuota) > 0 ? $_user->imapUser->emailMailQuota / 1024 : null;
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
. " Setting quota of user " . $_user->getId() . " to " . $limit);
$imap->setQuota($mailboxString, 'STORAGE', $limit);
}
}
/**
* get imap connection
*
* @return Zend_Mail_Protocol_Imap
* @throws Tinebase_Exception_AccessDenied
*/
protected function _getImapConnection()
{
if (! $this->_imap instanceof Zend_Mail_Protocol_Imap) {
$this->_imap = new Zend_Mail_Protocol_Imap($this->_config['host'], $this->_config['port'], $this->_config['ssl']);
$loginResult = $this->_imap->login($this->_config['admin'], $this->_config['password']);
if (! $loginResult) {
throw new Tinebase_Exception_AccessDenied('Could not login to cyrus server ' . $this->_config['host'] . ' with user ' . $this->_config['admin']);
}
}
return $this->_imap;
}
/**
* get mailbox string for users aka user.loginname
*
* @param string $_username the imap account name
* @throws Tinebase_Exception_NotFound
* @return string
*/
protected function _getUserMailbox($_username)
{
$imap = $this->_getImapConnection();
$namespaces = $imap->getNamespace();
if (!isset($namespaces['other'])) {
throw new Tinebase_Exception_NotFound('other namespace not found');
}
$mailboxString = $namespaces['other']['name'] . $this->_appendDomain($_username);
return $mailboxString;
}
/**
* updates email properties for an existing user
*
* @param Tinebase_Model_FullUser $_updatedUser
* @param Tinebase_Model_FullUser $_newUserProperties
*/
protected function _updateUser(Tinebase_Model_FullUser $_updatedUser, Tinebase_Model_FullUser $_newUserProperties)
{
$this->_setImapQuota($_newUserProperties);
$this->inspectGetUserByProperty($_updatedUser);
}
/**
* check if user exists already in dovecot user table
*
* @param Tinebase_Model_FullUser $_user
* @return boolean
*/
protected function _userExists(Tinebase_Model_FullUser $_user)
{
try {
$mailboxString = $this->_getUserMailbox($_user->accountLoginName);
} catch (Tinebase_Exception_NotFound $tenf) {
if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
. " Mailbox of user " . $_user->accountLoginName . " not found: " . $tenf->getMessage());
return false;
}
$imap = $this->_getImapConnection();
$mailboxes = $imap->listMailbox('', $mailboxString);
if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " search for {$mailboxString} in " . print_r($mailboxes, true));
// does mailbox exist at all?
if (!(isset($mailboxes[$mailboxString]) || array_key_exists($mailboxString, $mailboxes))) {
return false;
}
return true;
}
/**
* get quotas for specified mailbox for administrative purpose (instead of user's getquotaRoot)
*
* @param Zend_Mail_Protocol_Imap $_imap
* @param string $mailbox the mailbox (user.example)
* @return array
*/
protected function _adminGetQuota(Zend_Mail_Protocol_Imap $_imap = NULL, $mailbox)
{
$imap = ($_imap !== NULL) ? $_imap : $this->_getImapConnection();
$imap->sendRequest('GETQUOTA', array($mailbox), $tag);
$result = array();
while (! $imap->readLine($tokens, $tag)) {
if ($tokens[0] == 'QUOTA') {
if (! empty($tokens[2]) && is_array($tokens[2])) {
$result[strtoupper($tokens[2][0])] = array(
'resource' => strtoupper($tokens[2][0]),
'usage' => $tokens[2][1],
'limit' => $tokens[2][2]
);
}
}
}
return $result;
}
}