diff --git a/src/app/Backends/IMAP.php b/src/app/Backends/IMAP.php --- a/src/app/Backends/IMAP.php +++ b/src/app/Backends/IMAP.php @@ -107,11 +107,31 @@ $imap->setQuota($mailbox, ['storage' => $quota]); } + self::createDefaultFolders($imap, $user); + $imap->closeConnection(); return true; } + /** + * Create default folders for the user. + * + * @param \App\User $user User + */ + public static function createDefaultFolders($imap, User $user): void + { + foreach (\config('imap.default_folders') as $name => $folderconfig) { + try { + $mailbox = self::mailboxName($user->email, $name); + \Log::info("Creating default folder: $mailbox."); + self::createFolder($imap, $mailbox, true, $folderconfig['metadata']); + } catch (\Exception $e) { + \Log::warning("Failed to create the default folder" . $e->getMessage()); + } + } + } + /** * Delete a mailbox. * @@ -184,28 +204,13 @@ $settings = $resource->getSettings(['invitation_policy', 'folder']); $mailbox = self::toUTF7($settings['folder']); - // Mailbox already exists - 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 + $acl = null; if (!empty($settings['invitation_policy'])) { 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(); @@ -299,24 +304,7 @@ $acl = !empty($settings['acl']) ? json_decode($settings['acl'], true) : null; $mailbox = self::toUTF7($settings['folder']); - // Mailbox already exists - 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); + self::createFolder($imap, $mailbox, false, ['/shared/vendor/kolab/folder-type' => $folder->type], $acl); $imap->closeConnection(); @@ -459,6 +447,41 @@ return false; } + private static function mailboxName($username, $folderName) + { + $parts = explode('@', $username); + if (empty($folderName)) { + return self::toUTF7("user/$username"); + } else { + return self::toUTF7("user/{$parts[0]}/$folderName@{$parts[1]}"); + } + } + + /** + * 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); + + foreach (\config('imap.default_folders') as $mb => $_metadata) { + $mailbox = self::mailboxName($username, $mb); + if (!self::folderExists($imap, $mailbox)) { + \Log::info("Folder $mailbox does not exist."); + $imap->closeConnection(); + return false; + } + } + + $imap->closeConnection(); + return true; + } + /** * Check if we can connect to the imap server * @@ -515,6 +538,40 @@ $imap->closeConnection(); } + /** + * Create a folder and set some default properties + * + * @params $imap + * + * @returns 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; + } + + if (!$imap->createFolder($mailbox)) { + \Log::error("Failed to create mailbox {$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 */ diff --git a/src/config/imap.php b/src/config/imap.php --- a/src/config/imap.php +++ b/src/config/imap.php @@ -9,4 +9,16 @@ 'host' => env('IMAP_HOST', '172.18.0.5'), 'imap_port' => env('IMAP_PORT', 12143), 'guam_port' => env('IMAP_GUAM_PORT', 9143), + 'default_folders' => [ + 'Calendar' => [ + 'metadata' => [ + '/shared/vendor/kolab/folder-type' => 'calendar' + ], + ], + 'Addressbook' => [ + 'metadata' => [ + '/shared/vendor/kolab/folder-type' => 'addressbook' + ], + ], + ] ]; diff --git a/src/tests/Feature/Backends/IMAPTest.php b/src/tests/Feature/Backends/IMAPTest.php --- a/src/tests/Feature/Backends/IMAPTest.php +++ b/src/tests/Feature/Backends/IMAPTest.php @@ -107,6 +107,7 @@ $result = IMAP::createUser($user); $this->assertTrue($result); $this->assertTrue(IMAP::verifyAccount($user->email)); + $this->assertTrue(IMAP::verifyDefaultFolders($user->email)); $imap = $this->getImap(); $quota = $imap->getQuota('user/' . $user->email); @@ -128,6 +129,7 @@ $result = IMAP::verifyAccount($user->email); $this->assertFalse($result); + $this->assertFalse(IMAP::verifyDefaultFolders($user->email)); } /**