Changeset View
Changeset View
Standalone View
Standalone View
src/app/Backends/IMAP.php
<?php | <?php | ||||
namespace App\Backends; | namespace App\Backends; | ||||
use App\Domain; | |||||
use App\Group; | use App\Group; | ||||
use App\Resource; | use App\Resource; | ||||
use App\SharedFolder; | use App\SharedFolder; | ||||
use App\User; | use App\User; | ||||
class IMAP | class IMAP | ||||
{ | { | ||||
/** @const array Group settings used by the backend */ | /** @const array Group settings used by the backend */ | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | public static function createUser(User $user): bool | ||||
$config = self::getConfig(); | $config = self::getConfig(); | ||||
$imap = self::initIMAP($config); | $imap = self::initIMAP($config); | ||||
$mailbox = self::toUTF7('user/' . $user->email); | $mailbox = self::toUTF7('user/' . $user->email); | ||||
// Mailbox already exists | // Mailbox already exists | ||||
if (self::folderExists($imap, $mailbox)) { | if (self::folderExists($imap, $mailbox)) { | ||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
self::createDefaultFolders($user); | |||||
return true; | return true; | ||||
} | } | ||||
// Create the mailbox | // Create the mailbox | ||||
if (!$imap->createFolder($mailbox)) { | if (!$imap->createFolder($mailbox)) { | ||||
\Log::error("Failed to create mailbox {$mailbox}"); | \Log::error("Failed to create mailbox {$mailbox}"); | ||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
return false; | return false; | ||||
Show All 15 Lines | public static function createUser(User $user): bool | ||||
} | } | ||||
// Set quota | // Set quota | ||||
$quota = $user->countEntitlementsBySku('storage') * 1048576; | $quota = $user->countEntitlementsBySku('storage') * 1048576; | ||||
if ($quota) { | if ($quota) { | ||||
$imap->setQuota($mailbox, ['storage' => $quota]); | $imap->setQuota($mailbox, ['storage' => $quota]); | ||||
} | } | ||||
self::createDefaultFolders($user); | |||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Create default folders for the user. | |||||
* | |||||
* @param \App\User $user User | |||||
*/ | |||||
public static function createDefaultFolders(User $user): void | |||||
{ | |||||
if ($defaultFolders = \config('imap.default_folders')) { | |||||
$config = self::getConfig(); | |||||
// Log in as user to set private annotations and subscription state | |||||
$imap = self::initIMAP($config, $user->email); | |||||
foreach ($defaultFolders as $name => $folderconfig) { | |||||
try { | |||||
$mailbox = self::toUTF7($name); | |||||
self::createFolder($imap, $mailbox, true, $folderconfig['metadata']); | |||||
} catch (\Exception $e) { | |||||
\Log::warning("Failed to create the default folder" . $e->getMessage()); | |||||
} | |||||
} | |||||
$imap->closeConnection(); | |||||
} | |||||
} | |||||
/** | |||||
* Delete a mailbox. | * Delete a mailbox. | ||||
* | * | ||||
* @param \App\User $user User | * @param \App\User $user User | ||||
* | * | ||||
* @return bool True if a mailbox was deleted successfully, False otherwise | * @return bool True if a mailbox was deleted successfully, False otherwise | ||||
* @throws \Exception | * @throws \Exception | ||||
*/ | */ | ||||
public static function deleteUser(User $user): bool | public static function deleteUser(User $user): bool | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | class IMAP | ||||
public static function createResource(Resource $resource): bool | public static function createResource(Resource $resource): bool | ||||
{ | { | ||||
$config = self::getConfig(); | $config = self::getConfig(); | ||||
$imap = self::initIMAP($config); | $imap = self::initIMAP($config); | ||||
$settings = $resource->getSettings(['invitation_policy', 'folder']); | $settings = $resource->getSettings(['invitation_policy', 'folder']); | ||||
$mailbox = self::toUTF7($settings['folder']); | $mailbox = self::toUTF7($settings['folder']); | ||||
// Mailbox already exists | $acl = null; | ||||
if (self::folderExists($imap, $mailbox)) { | |||||
$imap->closeConnection(); | |||||
return true; | |||||
} | |||||
// Create the shared folder | |||||
if (!$imap->createFolder($mailbox)) { | |||||
\Log::error("Failed to create mailbox {$mailbox}"); | |||||
$imap->closeConnection(); | |||||
return false; | |||||
} | |||||
// Set folder type | |||||
$imap->setMetadata($mailbox, ['/shared/vendor/kolab/folder-type' => 'event']); | |||||
// Set ACL | |||||
if (!empty($settings['invitation_policy'])) { | if (!empty($settings['invitation_policy'])) { | ||||
if (preg_match('/^manual:(\S+@\S+)$/', $settings['invitation_policy'], $m)) { | if (preg_match('/^manual:(\S+@\S+)$/', $settings['invitation_policy'], $m)) { | ||||
self::aclUpdate($imap, $mailbox, ["{$m[1]}, full"]); | $acl = ["{$m[1]}, full"]; | ||||
} | } | ||||
} | } | ||||
self::createFolder($imap, $mailbox, false, ['/shared/vendor/kolab/folder-type' => 'event'], $acl); | |||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Update a resource. | * Update a resource. | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | class IMAP | ||||
{ | { | ||||
$config = self::getConfig(); | $config = self::getConfig(); | ||||
$imap = self::initIMAP($config); | $imap = self::initIMAP($config); | ||||
$settings = $folder->getSettings(['acl', 'folder']); | $settings = $folder->getSettings(['acl', 'folder']); | ||||
$acl = !empty($settings['acl']) ? json_decode($settings['acl'], true) : null; | $acl = !empty($settings['acl']) ? json_decode($settings['acl'], true) : null; | ||||
$mailbox = self::toUTF7($settings['folder']); | $mailbox = self::toUTF7($settings['folder']); | ||||
// Mailbox already exists | self::createFolder($imap, $mailbox, false, ['/shared/vendor/kolab/folder-type' => $folder->type], $acl); | ||||
if (self::folderExists($imap, $mailbox)) { | |||||
$imap->closeConnection(); | |||||
return true; | |||||
} | |||||
// Create the mailbox | |||||
if (!$imap->createFolder($mailbox)) { | |||||
\Log::error("Failed to create mailbox {$mailbox}"); | |||||
$imap->closeConnection(); | |||||
return false; | |||||
} | |||||
// Set folder type | |||||
$imap->setMetadata($mailbox, ['/shared/vendor/kolab/folder-type' => $folder->type]); | |||||
// Set ACL | |||||
self::aclUpdate($imap, $mailbox, $acl); | |||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Update a shared folder. | * Update a shared folder. | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | public static function verifyAccount(string $username): bool | ||||
return true; | return true; | ||||
} | } | ||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Check if an account is set up | |||||
* | |||||
* @param string $username User login (email address) | |||||
* | |||||
* @return bool True if an account exists and is set up, False otherwise | |||||
*/ | |||||
public static function verifyDefaultFolders(string $username): bool | |||||
{ | |||||
$config = self::getConfig(); | |||||
$imap = self::initIMAP($config, $username); | |||||
foreach (\config('imap.default_folders') as $mb => $_metadata) { | |||||
$mailbox = self::toUTF7($mb); | |||||
if (!self::folderExists($imap, $mailbox)) { | |||||
$imap->closeConnection(); | |||||
machniak: I'd remove that info() call. | |||||
return false; | |||||
} | |||||
} | |||||
$imap->closeConnection(); | |||||
return true; | |||||
} | |||||
/** | |||||
* Check if we can connect to the imap server | * Check if we can connect to the imap server | ||||
* | * | ||||
* @return bool True on success | * @return bool True on success | ||||
*/ | */ | ||||
public static function healthcheck(): bool | public static function healthcheck(): bool | ||||
{ | { | ||||
$config = self::getConfig(); | $config = self::getConfig(); | ||||
$imap = self::initIMAP($config); | $imap = self::initIMAP($config); | ||||
Show All 40 Lines | public static function aclCleanup(string $ident, string $domain = ''): void | ||||
} | } | ||||
array_walk($folders, $callback); | array_walk($folders, $callback); | ||||
$imap->closeConnection(); | $imap->closeConnection(); | ||||
} | } | ||||
/** | /** | ||||
* Create a folder and set some default properties | |||||
* | |||||
* @param \rcube_imap_generic $imap The imap instance | |||||
Done Inline ActionsMissing parameters. machniak: Missing parameters. | |||||
* @param string $mailbox Mailbox name | |||||
* @param bool $subscribe Subscribe to the folder | |||||
Done Inline Actions@return without s. machniak: `@return` without s. | |||||
* @param array $metadata Metadata to set on the folder | |||||
* @param array $acl Acl to set on the folder | |||||
* | |||||
* @return bool True when having a folder created, False if it already existed. | |||||
* @throws \Exception | |||||
*/ | |||||
private static function createFolder($imap, string $mailbox, $subscribe = false, $metadata = null, $acl = null) | |||||
{ | |||||
if (self::folderExists($imap, $mailbox)) { | |||||
return false; | |||||
Done Inline Actions"Failed to create mailbox Trash" might not be very helpful in log if there's no context. I'd remove this error() call. Exception should get logged with some context. machniak: "Failed to create mailbox Trash" might not be very helpful in log if there's no context. I'd… | |||||
} | |||||
if (!$imap->createFolder($mailbox)) { | |||||
throw new \Exception("Failed to create mailbox {$mailbox}"); | |||||
} | |||||
if ($acl) { | |||||
self::aclUpdate($imap, $mailbox, $acl, true); | |||||
} | |||||
if ($subscribe) { | |||||
$imap->subscribe($mailbox); | |||||
} | |||||
foreach ($metadata as $key => $value) { | |||||
$imap->setMetadata($mailbox, [$key => $value]); | |||||
} | |||||
return true; | |||||
} | |||||
/** | |||||
* Convert Kolab ACL into IMAP user->rights array | * Convert Kolab ACL into IMAP user->rights array | ||||
*/ | */ | ||||
private static function aclToImap($acl): array | private static function aclToImap($acl): array | ||||
{ | { | ||||
if (empty($acl)) { | if (empty($acl)) { | ||||
return []; | return []; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 124 Lines • Show Last 20 Lines |
I'd remove that info() call.