Skip to content

Commit

Permalink
Add check before sending email that email address is valid
Browse files Browse the repository at this point in the history
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
  • Loading branch information
CarlSchwan committed Jan 11, 2022
1 parent d4a5e48 commit 50da844
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 15 deletions.
10 changes: 10 additions & 0 deletions apps/sharebymail/lib/ShareByMailProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,16 @@ protected function createMailShare(IShare $share) {
$share->getNote()
);

if ($this->mailer->validateMailAddress($share->getSharedWith())) {
$this->removeShareFromTable($shareId);
$e = new HintException('Failed to send share by mail. Got an invalid email address: ' . $share->getSharedWith(),
$this->l->t('Failed to send share by email. Got an invalid email address'));
$this->logger->error($e->getMessage(), [
'message' => 'Failed to send share by mail. Got an invalid email address ' . $share->getSharedWith(),
'app' => 'sharebymail',
]);
}

try {
$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
['token' => $share->getToken()]);
Expand Down
15 changes: 8 additions & 7 deletions lib/private/Collaboration/Collaborators/MailPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IShare;
use OCP\Mail\IMailer;

class MailPlugin implements ISearchPlugin {
/* @var bool */
Expand All @@ -64,19 +65,23 @@ class MailPlugin implements ISearchPlugin {
private $knownUserService;
/** @var IUserSession */
private $userSession;
/** @var IMailer */
private $mailer;

public function __construct(IManager $contactsManager,
ICloudIdManager $cloudIdManager,
IConfig $config,
IGroupManager $groupManager,
KnownUserService $knownUserService,
IUserSession $userSession) {
IUserSession $userSession,
IMailer $mailer) {
$this->contactsManager = $contactsManager;
$this->cloudIdManager = $cloudIdManager;
$this->config = $config;
$this->groupManager = $groupManager;
$this->knownUserService = $knownUserService;
$this->userSession = $userSession;
$this->mailer = $mailer;

$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
$this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
Expand Down Expand Up @@ -247,14 +252,10 @@ public function search($search, $limit, $offset, ISearchResult $searchResult) {
$userResults['wide'] = array_slice($userResults['wide'], $offset, $limit);
}

[$username, $domain] = explode('@', $search);
$domain = idn_to_ascii($domain);
$searchIdn = $username . '@' . $domain;

if (!$searchResult->hasExactIdMatch($emailType) && filter_var($searchIdn, FILTER_VALIDATE_EMAIL)) {
if (!$searchResult->hasExactIdMatch($emailType) && $this->mailer->validateMailAddress($search)) {
$result['exact'][] = [
'label' => $search,
'uuid' => $searchIdn,
'uuid' => $search,
'value' => [
'shareType' => IShare::TYPE_EMAIL,
'shareWith' => $search,
Expand Down
58 changes: 50 additions & 8 deletions tests/lib/Collaboration/Collaborators/MailPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share\IShare;
use OCP\Mail\IMailer;
use Test\TestCase;

class MailPluginTest extends TestCase {
Expand Down Expand Up @@ -64,6 +65,9 @@ class MailPluginTest extends TestCase {
/** @var IUserSession|\PHPUnit\Framework\MockObject\MockObject */
protected $userSession;

/** @var IMailer|\PHPUnit\Framework\MockObject\MockObject */
protected $mailer;

protected function setUp(): void {
parent::setUp();

Expand All @@ -72,6 +76,7 @@ protected function setUp(): void {
$this->groupManager = $this->createMock(IGroupManager::class);
$this->knownUserService = $this->createMock(KnownUserService::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->mailer = $this->createMock(IMailer::class);
$this->cloudIdManager = new CloudIdManager($this->contactsManager, $this->createMock(IURLGenerator::class), $this->createMock(IUserManager::class));

$this->searchResult = new SearchResult();
Expand All @@ -84,7 +89,8 @@ public function instantiatePlugin() {
$this->config,
$this->groupManager,
$this->knownUserService,
$this->userSession
$this->userSession,
$this->mailer
);
}

Expand All @@ -97,7 +103,7 @@ public function instantiatePlugin() {
* @param array $expected
* @param bool $reachedEnd
*/
public function testSearch($searchTerm, $contacts, $shareeEnumeration, $expected, $exactIdMatch, $reachedEnd) {
public function testSearch($searchTerm, $contacts, $shareeEnumeration, $expected, $exactIdMatch, $reachedEnd, $validEmail) {
$this->config->expects($this->any())
->method('getAppValue')
->willReturnCallback(
Expand All @@ -117,6 +123,9 @@ function ($appName, $key, $default) use ($shareeEnumeration) {
$this->userSession->method('getUser')
->willReturn($currentUser);

$this->mailer->method('validateMailAddress')
->willReturn($validEmail);

$this->contactsManager->expects($this->any())
->method('search')
->willReturnCallback(function ($search, $searchAttributes) use ($searchTerm, $contacts) {
Expand All @@ -137,9 +146,9 @@ function ($appName, $key, $default) use ($shareeEnumeration) {
public function dataGetEmail() {
return [
// data set 0
['test', [], true, ['emails' => [], 'exact' => ['emails' => []]], false, false],
['test', [], true, ['emails' => [], 'exact' => ['emails' => []]], false, false, false],
// data set 1
['test', [], false, ['emails' => [], 'exact' => ['emails' => []]], false, false],
['test', [], false, ['emails' => [], 'exact' => ['emails' => []]], false, false, false],
// data set 2
[
'test@remote.com',
Expand All @@ -148,6 +157,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@remote.com', 'label' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 3
[ // no valid email address
Expand All @@ -157,6 +167,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 4
[
Expand All @@ -166,6 +177,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@remote.com', 'label' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 5
[
Expand Down Expand Up @@ -193,6 +205,7 @@ public function dataGetEmail() {
['emails' => [['uuid' => 'uid1', 'name' => 'User @ Localhost', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 6
[
Expand Down Expand Up @@ -221,6 +234,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 7
[
Expand Down Expand Up @@ -248,6 +262,7 @@ public function dataGetEmail() {
['emails' => [['uuid' => 'uid1', 'name' => 'User @ Localhost', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]], 'exact' => ['emails' => [['label' => 'test@remote.com', 'uuid' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 8
[
Expand Down Expand Up @@ -276,6 +291,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['label' => 'test@remote.com', 'uuid' => 'test@remote.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@remote.com']]]]],
false,
false,
true,
],
// data set 9
[
Expand Down Expand Up @@ -303,6 +319,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['name' => 'User @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]],
true,
false,
false,
],
// data set 10
[
Expand Down Expand Up @@ -330,6 +347,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['name' => 'User @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User @ Localhost (username@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'username@localhost']]]]],
true,
false,
false,
],
// data set 11
// contact with space
Expand Down Expand Up @@ -358,6 +376,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => [['name' => 'User Name @ Localhost', 'uuid' => 'uid1', 'type' => '', 'label' => 'User Name @ Localhost (user name@localhost)', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'user name@localhost']]]]],
true,
false,
false,
],
// data set 12
// remote with space, no contact
Expand Down Expand Up @@ -387,6 +406,7 @@ public function dataGetEmail() {
['emails' => [], 'exact' => ['emails' => []]],
false,
false,
false,
],
// data set 13
// Local user found by email
Expand All @@ -405,6 +425,7 @@ public function dataGetEmail() {
['users' => [], 'exact' => ['users' => [['uuid' => 'uid1', 'name' => 'User', 'label' => 'User (test@example.com)','value' => ['shareType' => IShare::TYPE_USER, 'shareWith' => 'test'], 'shareWithDisplayNameUnique' => 'test@example.com']]]],
true,
false,
true,
],
// data set 14
// Current local user found by email => no result
Expand All @@ -423,6 +444,7 @@ public function dataGetEmail() {
['exact' => []],
false,
false,
true,
],
// data set 15
// Pagination and "more results" for user matches byyyyyyy emails
Expand Down Expand Up @@ -465,6 +487,7 @@ public function dataGetEmail() {
], 'emails' => [], 'exact' => ['users' => [], 'emails' => []]],
false,
true,
false,
],
// data set 16
// Pagination and "more results" for normal emails
Expand Down Expand Up @@ -503,6 +526,7 @@ public function dataGetEmail() {
], 'exact' => ['emails' => []]],
false,
true,
false,
],
// data set 17
// multiple email addresses with type
Expand Down Expand Up @@ -536,6 +560,18 @@ public function dataGetEmail() {
]]],
false,
false,
false,
],
// data set 18
// idn email
[
'test@lölölölölölölöl.com',
[],
true,
['emails' => [], 'exact' => ['emails' => [['uuid' => 'test@lölölölölölölöl.com', 'label' => 'test@lölölölölölölöl.com', 'value' => ['shareType' => IShare::TYPE_EMAIL, 'shareWith' => 'test@lölölölölölölöl.com']]]]],
false,
false,
true,
],
];
}
Expand All @@ -550,7 +586,7 @@ public function dataGetEmail() {
* @param bool $reachedEnd
* @param array groups
*/
public function testSearchGroupsOnly($searchTerm, $contacts, $expected, $exactIdMatch, $reachedEnd, $userToGroupMapping) {
public function testSearchGroupsOnly($searchTerm, $contacts, $expected, $exactIdMatch, $reachedEnd, $userToGroupMapping, $validEmail) {
$this->config->expects($this->any())
->method('getAppValue')
->willReturnCallback(
Expand All @@ -573,6 +609,9 @@ function ($appName, $key, $default) {
->method('getUID')
->willReturn('currentUser');

$this->mailer->method('validateMailAddress')
->willReturn($validEmail);

$this->contactsManager->expects($this->any())
->method('search')
->willReturnCallback(function ($search, $searchAttributes) use ($searchTerm, $contacts) {
Expand Down Expand Up @@ -626,7 +665,8 @@ public function dataGetEmailGroupsOnly() {
[
"currentUser" => ["group1"],
"User" => ["group1"]
]
],
false,
],
// The user `User` cannot share with the current user
[
Expand All @@ -646,7 +686,8 @@ public function dataGetEmailGroupsOnly() {
[
"currentUser" => ["group1"],
"User" => ["group2"]
]
],
false,
],
// The user `User` cannot share with the current user, but there is an exact match on the e-mail address -> share by e-mail
[
Expand All @@ -666,7 +707,8 @@ public function dataGetEmailGroupsOnly() {
[
"currentUser" => ["group1"],
"User" => ["group2"]
]
],
true,
]
];
}
Expand Down

0 comments on commit 50da844

Please sign in to comment.