diff --git a/src/app/Policy/Greylist/Request.php b/src/app/Policy/Greylist/Request.php --- a/src/app/Policy/Greylist/Request.php +++ b/src/app/Policy/Greylist/Request.php @@ -242,7 +242,7 @@ { $recipients = \App\Utils::findObjectsByRecipientAddress($this->request['recipient']); - if (sizeof($recipients) > 1) { + if (count($recipients) > 1) { \Log::warning( "Only taking the first recipient from the request for {$this->request['recipient']}" ); @@ -250,11 +250,9 @@ if (count($recipients) >= 1) { foreach ($recipients as $recipient) { - if ($recipient) { - $this->recipientID = $recipient->id; - $this->recipientType = get_class($recipient); - break; - } + $this->recipientID = $recipient->id; + $this->recipientType = get_class($recipient); + break; } } else { $recipient = null; diff --git a/src/app/Utils.php b/src/app/Utils.php --- a/src/app/Utils.php +++ b/src/app/Utils.php @@ -180,14 +180,18 @@ /** * Find an object that is the recipient for the specified address. * - * @param string $address + * @param string $address E-mail address * - * @return array + * @return array<\App\User|\App\Resource|\App\SharedFolder> List of objects */ public static function findObjectsByRecipientAddress($address) { $address = \App\Utils::normalizeAddress($address); + if (strpos($address, '@') === false) { + return []; + } + list($local, $domainName) = explode('@', $address); $domain = \App\Domain::where('namespace', $domainName)->first(); @@ -196,34 +200,67 @@ return []; } + // Find user/shared-folder/resource with specified address + // Note: Groups also have email address, but they aren't mailrecipients in LDAP + $user = \App\User::where('email', $address)->first(); if ($user) { return [$user]; } - $userAliases = \App\UserAlias::where('alias', $address)->get(); + $folder = \App\SharedFolder::where('email', $address)->first(); - if (count($userAliases) > 0) { - $users = []; + if ($folder) { + return [$folder]; + } - foreach ($userAliases as $userAlias) { - $users[] = $userAlias->user; - } + $resource = \App\Resource::where('email', $address)->first(); - return $users; + if ($resource) { + return [$resource]; } - $userAliases = \App\UserAlias::where('alias', "catchall@{$domain->namespace}")->get(); + // Find aliases with specified address + // TODO: Folders and users can have the same alias, should we merge the result (and return both)? - if (count($userAliases) > 0) { - $users = []; + $users = \App\User::select('users.*') + ->join('user_aliases', 'user_aliases.user_id', '=', 'users.id') + ->where('alias', $address) + ->get(); - foreach ($userAliases as $userAlias) { - $users[] = $userAlias->user; - } + if (count($users) > 0) { + return $users->all(); + } + + $folders = \App\SharedFolder::select('shared_folders.*') + ->join('shared_folder_aliases', 'shared_folder_aliases.shared_folder_id', '=', 'shared_folders.id') + ->where('alias', $address) + ->get(); + + if (count($folders) > 0) { + return $folders->all(); + } + + // Use catchall@ alias if exists + // TODO: Folders and users can have the same alias, should we merge the result (and return both)? + + $users = \App\User::select('users.*') + ->join('user_aliases', 'user_aliases.user_id', '=', 'users.id') + ->where('alias', "catchall@{$domain->namespace}") + ->get(); + + if (count($users) > 0) { + return $users->all(); + } + + $folders = \App\SharedFolder::select('shared_folders.*') + ->join('shared_folder_aliases', 'shared_folder_aliases.shared_folder_id', '=', 'shared_folders.id') + ->where('alias', "catchall@{$domain->namespace}") + ->get(); - return $users; + if (count($folders) > 0) { + return $folders->all(); } return []; diff --git a/src/tests/Feature/UtilsTest.php b/src/tests/Feature/UtilsTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/UtilsTest.php @@ -0,0 +1,111 @@ +deleteTestUser('UserAccountA@UserAccount.com'); + $this->deleteTestDomain('UserAccount.com'); + $this->deleteTestSharedFolder('folder-test@kolabnow.com'); + $this->deleteTestResource('resource-test@kolabnow.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestUser('UserAccountA@UserAccount.com'); + $this->deleteTestDomain('UserAccount.com'); + $this->deleteTestSharedFolder('folder-test@kolabnow.com'); + $this->deleteTestResource('resource-test@kolabnow.com'); + + parent::tearDown(); + } + + /** + * Test Utils::findObjectsByRecipientAddress() + */ + public function testFindObjectsByRecipientAddress(): void + { + $result = Utils::findObjectsByRecipientAddress('unknown'); + $this->assertCount(0, $result); + + $result = Utils::findObjectsByRecipientAddress('unknown@unknow.org'); + $this->assertCount(0, $result); + + $result = Utils::findObjectsByRecipientAddress('unknown@kolab.org'); + $this->assertCount(0, $result); + + // Users + + $user = $this->getTestUser('UserAccountA@UserAccount.com'); + $domain = $this->getTestDomain('UserAccount.com', [ + 'status' => Domain::STATUS_NEW | Domain::STATUS_ACTIVE, + 'type' => Domain::TYPE_PUBLIC, + ]); + + $result = Utils::findObjectsByRecipientAddress('UserAccountA@UserAccount.com'); + + $this->assertCount(1, $result); + $this->assertSame($user->email, $result[0]->email); + + $user->setAliases(['test@UserAccount.com']); + + $result = Utils::findObjectsByRecipientAddress('test@UserAccount.com'); + + $this->assertCount(1, $result); + $this->assertSame($user->email, $result[0]->email); + + $user->setAliases(['catchall@UserAccount.com']); + + $result = Utils::findObjectsByRecipientAddress('unknown@UserAccount.com'); + + $this->assertCount(1, $result); + $this->assertSame($user->email, $result[0]->email); + + // Shared folders + + $folder = $this->getTestSharedFolder('folder-test@kolabnow.com'); + $folder->setAliases(['test@kolabnow.com']); + + $result = Utils::findObjectsByRecipientAddress('folder-test@kolabnow.com'); + + $this->assertCount(1, $result); + $this->assertSame($folder->email, $result[0]->email); + + $result = Utils::findObjectsByRecipientAddress('test@kolabnow.com'); + + $this->assertCount(1, $result); + $this->assertSame($folder->email, $result[0]->email); + + $folder->setAliases(['catchall@kolabnow.com']); + + $result = Utils::findObjectsByRecipientAddress('unknown@kolabnow.com'); + + $this->assertCount(1, $result); + $this->assertSame($folder->email, $result[0]->email); + + // Resources + + $resource = $this->getTestResource('resource-test@kolabnow.com'); + + $result = Utils::findObjectsByRecipientAddress('resource-test@kolabnow.com'); + + $this->assertCount(1, $result); + $this->assertSame($resource->email, $result[0]->email); + + // TODO: Test multiple entries result + } +}