From c253112cf77411ee374ea29a9566cdd28d3e544d Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Fri, 5 Jul 2024 14:02:53 +0200 Subject: chore(files_sharing): refactor mail handling Signed-off-by: skjnldsv --- .../lib/Controller/ShareAPIController.php | 33 +++++++++++++++- apps/sharebymail/lib/ShareByMailProvider.php | 45 +++++++++++++++------- 2 files changed, 64 insertions(+), 14 deletions(-) (limited to 'apps') diff --git a/apps/files_sharing/lib/Controller/ShareAPIController.php b/apps/files_sharing/lib/Controller/ShareAPIController.php index 5e7e2b9c872..72ebd39ea07 100644 --- a/apps/files_sharing/lib/Controller/ShareAPIController.php +++ b/apps/files_sharing/lib/Controller/ShareAPIController.php @@ -2040,18 +2040,49 @@ class ShareAPIController extends OCSController { */ #[NoAdminRequired] #[BruteForceProtection(action: 'sendShareEmail')] - public function sendShareEmail(string $id, $emails = []) { + public function sendShareEmail(string $id, $password = '') { try { $share = $this->getShareById($id); + if (!$this->canAccessShare($share, false)) { + throw new OCSNotFoundException($this->l->t('Wrong share ID, share does not exist')); + } + + if (!$this->canEditShare($share)) { + throw new OCSForbiddenException('You are not allowed to send mail notifications'); + } + + // For mail and link shares, the user must be + // the owner of the share, not only the file owner. + if ($share->getShareType() === IShare::TYPE_EMAIL + || $share->getShareType() === IShare::TYPE_LINK){ + if ($share->getSharedBy() !== $this->currentUser) { + throw new OCSForbiddenException('You are not allowed to send mail notifications'); + } + } + try { $provider = $this->factory->getProviderForType($share->getShareType()); if (!($provider instanceof IShareProviderWithNotification)) { throw new OCSBadRequestException($this->l->t('No mail notification configured for this share type')); } + // Circumvent the password encrypted data by + // setting the password clear. We're not storing + // the password clear, it is just a temporary + // object manipulation. The password will stay + // encrypted in the database. + if ($share->getPassword() && $share->getPassword() !== $password) { + if (!$this->shareManager->checkPassword($share, $password)) { + throw new OCSBadRequestException($this->l->t('Wrong password')); + } + $share = $share->setPassword($password); + } + $provider->sendMailNotification($share); return new JSONResponse(['message' => 'ok']); + } catch(OCSBadRequestException $e) { + throw $e; } catch (Exception $e) { throw new OCSException($this->l->t('Error while sending mail notification')); } diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php index 3ff4f3db82e..63f80f5db5f 100644 --- a/apps/sharebymail/lib/ShareByMailProvider.php +++ b/apps/sharebymail/lib/ShareByMailProvider.php @@ -101,18 +101,12 @@ class ShareByMailProvider implements IShareProviderWithNotification { $shareId = $this->createMailShare($share); - // Sends share password to receiver when it's a permanent one (otherwise she will have to request it via the showShare UI) - // or to owner when the password shall be given during a Talk session - if ($this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false) === false || $share->getSendPasswordByTalk()) { - $send = $this->sendPassword($share, $password); - if ($passwordEnforced && $send === false) { - $this->sendPasswordToOwner($share, $password); - } - } - $this->createShareActivity($share); $data = $this->getRawShare($shareId); + // Temporary set the clear password again to send it by mail + $data['password'] = $password; + return $this->createShareObject($data); } @@ -260,6 +254,21 @@ class ShareByMailProvider implements IShareProviderWithNotification { $share->getExpirationDate(), $share->getNote() ); + + // If we have a password set, we send it to the recipient + if ($share->getPassword()) { + // Sends share password to receiver when it's a permanent one (otherwise she will have to request it via the showShare UI) + // or to owner when the password shall be given during a Talk session + $passwordExpire = $this->config->getSystemValue('sharing.enable_mail_link_password_expiration', false); + $passwordEnforced = $this->shareManager->shareApiLinkEnforcePassword(); + if ($passwordExpire === false || $share->getSendPasswordByTalk()) { + $send = $this->sendPassword($share, $share->getPassword()); + if ($passwordEnforced && $send === false) { + $this->sendPasswordToOwner($share, $share->getPassword()); + } + } + } + return true; } catch (HintException $hintException) { $this->logger->error('Failed to send share by mail.', [ @@ -289,7 +298,7 @@ class ShareByMailProvider implements IShareProviderWithNotification { * @param string $note note * @throws \Exception If mail couldn't be sent */ - public function sendEmail( + protected function sendEmail( string $filename, string $link, string $initiator, @@ -318,6 +327,7 @@ class ShareByMailProvider implements IShareProviderWithNotification { if ($note !== '') { $emailTemplate->addBodyText(htmlspecialchars($note), $note); } + $emailTemplate->addBodyText( htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')), $text @@ -354,13 +364,21 @@ class ShareByMailProvider implements IShareProviderWithNotification { } $message->useTemplate($emailTemplate); - $this->mailer->send($message); + $failedRecipients = $this->mailer->send($message); + if (!empty($failedRecipients)) { + $this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients)); + return; + } } /** - * send password to recipient of a mail share + * Send password to recipient of a mail share + * Will return false if + * 1. the password is empty + * 2. the setting to send the password by mail is disabled + * 3. the share is set to send the password by talk */ - public function sendPassword(IShare $share, string $password): bool { + protected function sendPassword(IShare $share, string $password): bool { $filename = $share->getNode()->getName(); $initiator = $share->getSharedBy(); $shareWith = $share->getSharedWith(); @@ -660,6 +678,7 @@ class ShareByMailProvider implements IShareProviderWithNotification { ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE)) ->set('note', $qb->createNamedParameter($share->getNote())) ->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT)) + ->set('mail_send', $qb->createNamedParameter(1)) ->executeStatement(); if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') { -- cgit v1.2.3