-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: SebastianKrupinski <[email protected]>
- Loading branch information
1 parent
c0f8c2a
commit 9b4486a
Showing
9 changed files
with
1,077 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,6 +83,29 @@ public function findByUserId(string $userId): array { | |
return $this->findEntities($query); | ||
} | ||
|
||
/** | ||
* Finds a mail account(s) by user id and mail address | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @param string $userId system user id | ||
* @param string $address mail address (e.g. [email protected]) | ||
* | ||
* @return MailAccount[] | ||
* | ||
* @throws DoesNotExistException | ||
*/ | ||
public function findByUserIdAndAddress(string $userId, string $address): array { | ||
$qb = $this->db->getQueryBuilder(); | ||
$query = $qb | ||
->select('*') | ||
->from($this->getTableName()) | ||
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId))) | ||
->andWhere($qb->expr()->eq('email', $qb->createNamedParameter($address))); | ||
|
||
return $this->findEntities($query); | ||
} | ||
|
||
/** | ||
* @throws DoesNotExistException | ||
* @throws MultipleObjectsReturnedException | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
namespace OCA\Mail\Provider\Command; | ||
|
||
use OCA\Mail\Db\LocalMessage; | ||
use OCA\Mail\Service\AccountService; | ||
use OCA\Mail\Service\Attachment\AttachmentService; | ||
use OCA\Mail\Service\OutboxService; | ||
use OCA\Mail\Service\SmimeService; | ||
use OCP\IConfig; | ||
use OCP\AppFramework\Utility\ITimeFactory; | ||
use OCP\Mail\Provider\Exception\SendException; | ||
use OCP\Mail\Provider\IMessage; | ||
|
||
class MessageSend { | ||
|
||
public function __construct( | ||
protected IConfig $config, | ||
protected ITimeFactory $time, | ||
protected AccountService $accountService, | ||
protected OutboxService $outboxService, | ||
protected AttachmentService $attachmentService | ||
) { | ||
} | ||
|
||
public function perform(string $userId, string $serviceId, IMessage $message, array $option = []): LocalMessage { | ||
// find user mail account details | ||
$account = $this->accountService->find($userId, (int) $serviceId); | ||
// convert mail provider message to mail app message | ||
$localMessage = new LocalMessage(); | ||
$localMessage->setType($localMessage::TYPE_OUTGOING); | ||
$localMessage->setAccountId($account->getId()); | ||
$localMessage->setSubject($message->getSubject()); | ||
$localMessage->setBody($message->getBody()); | ||
$localMessage->setHtml(true); | ||
$localMessage->setSendAt($this->time->getTime()); | ||
|
||
// convert all mail provider attachments to local attachments | ||
$attachments = []; | ||
if (count($message->getAttachments()) > 0) { | ||
// iterate attachments and save them | ||
foreach ($message->getAttachments() as $entry) { | ||
// determine if required parameters are set | ||
if (empty($entry->getName()) || empty($entry->getType()) || empty($entry->getContents())) { | ||
throw new SendException("Invalid Attachment Parameter: MUST contain values for Name, Type and Contents"); | ||
} | ||
// convert mail provider attachment to mail app attachment | ||
$attachments[] = $this->attachmentService->addFileFromString( | ||
$userId, | ||
$entry->getName(), | ||
$entry->getType(), | ||
$entry->getContents() | ||
)->jsonSerialize(); | ||
} | ||
} | ||
// determine if required To address is set | ||
if (empty($message->getTo()) || empty($message->getTo()[0]->getAddress())) { | ||
throw new SendException("Invalid Message Parameter: MUST contain at least one TO address with a valid address"); | ||
} | ||
// convert recipiant addresses | ||
$to = $this->convertAddressArray($message->getTo()); | ||
$cc = $this->convertAddressArray($message->getCc()); | ||
$bcc = $this->convertAddressArray($message->getBcc()); | ||
// save message for sending | ||
$localMessage = $this->outboxService->saveMessage( | ||
$account, | ||
$localMessage, | ||
$to, | ||
$cc, | ||
$bcc, | ||
$attachments | ||
); | ||
|
||
// evaluate if job scheduler is NOT cron, send message right away otherwise let cron job handle it | ||
if ($this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax') !== 'cron') { | ||
$localMessage = $this->outboxService->sendMessage($localMessage, $account); | ||
} | ||
|
||
return $localMessage; | ||
|
||
} | ||
|
||
protected function convertAddressArray(array|null $in) { | ||
// construct place holder | ||
$out = []; | ||
// convert format | ||
foreach ($in as $entry) { | ||
$out[] = (!empty($entry->getLabel())) ? ['email' => $entry->getAddress(), 'label' => $entry->getLabel()] : ['email' => $entry->getAddress()]; | ||
} | ||
// return converted addressess | ||
return $out; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
namespace OCA\Mail\Provider; | ||
|
||
use OCA\Mail\Account; | ||
use OCA\Mail\Service\AccountService; | ||
use OCP\Mail\Provider\Address as MailAddress; | ||
use OCP\Mail\Provider\IProvider; | ||
use OCP\Mail\Provider\IService; | ||
use Psr\Container\ContainerInterface; | ||
|
||
class MailProvider implements IProvider { | ||
|
||
private ?array $ServiceCollection = []; | ||
|
||
public function __construct( | ||
protected ContainerInterface $container, | ||
protected AccountService $accountService | ||
) { | ||
} | ||
|
||
/** | ||
* arbitrary unique text string identifying this provider | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @return string id of this provider (e.g. UUID or 'IMAP/SMTP' or anything else) | ||
*/ | ||
public function id(): string { | ||
return 'mail-application'; | ||
} | ||
|
||
/** | ||
* localized human frendly name of this provider | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @return string label/name of this provider (e.g. Plain Old IMAP/SMTP) | ||
*/ | ||
public function label(): string { | ||
return 'Mail Application'; | ||
} | ||
|
||
/** | ||
* determain if any services are configured for a specific user | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @param string $userId user id | ||
* | ||
* @return bool true if any services are configure for the user | ||
*/ | ||
public function hasServices(string $userId): bool { | ||
return (count($this->listServices($userId)) > 0); | ||
} | ||
|
||
/** | ||
* retrieve collection of services for a specific user | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @param string $userId user id | ||
* | ||
* @return array<string,IService> collection of service id and object ['1' => IServiceObject] | ||
*/ | ||
public function listServices(string $userId): array { | ||
|
||
try { | ||
// retrieve service(s) details from data store | ||
$accounts = $this->accountService->findByUserId($userId); | ||
} catch (\Throwable $th) { | ||
return []; | ||
} | ||
// construct temporary collection | ||
$services = []; | ||
// add services to collection | ||
foreach ($accounts as $entry) { | ||
// extract values | ||
$serviceId = (string) $entry->getId(); | ||
$label = $entry->getName(); | ||
$address = new MailAddress($entry->getEmail(), $entry->getName()); | ||
// add service to collection | ||
$services[$serviceId] = new MailService($this->container, $userId, $serviceId, $label, $address); | ||
} | ||
// return list of services for user | ||
return $services; | ||
|
||
} | ||
|
||
/** | ||
* retrieve a service with a specific id | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @param string $userId user id | ||
* @param string $serviceId service id | ||
* | ||
* @return IService|null returns service object or null if none found | ||
*/ | ||
public function findServiceById(string $userId, string $serviceId): IService | null { | ||
|
||
// evaluate if id is a number | ||
if (is_numeric($serviceId)) { | ||
try { | ||
// retrieve service details from data store | ||
$account = $this->accountService->find($userId, (int) $serviceId); | ||
} catch(\Throwable $th) { | ||
return null; | ||
} | ||
} | ||
// evaluate if service details where found | ||
if ($account instanceof Account) { | ||
// extract values | ||
$serviceId = (string) $account->getId(); | ||
$label = $account->getName(); | ||
$address = new MailAddress($account->getEmail(), $account->getName()); | ||
// return mail service object | ||
return new MailService($this->container, $userId, $serviceId, $label, $address); | ||
} | ||
|
||
return null; | ||
|
||
} | ||
|
||
/** | ||
* retrieve a service for a specific mail address | ||
* | ||
* @since 4.0.0 | ||
* | ||
* @param string $userId user id | ||
* @param string $address mail address (e.g. [email protected]) | ||
* | ||
* @return IService returns service object or null if none found | ||
*/ | ||
public function findServiceByAddress(string $userId, string $address): IService | null { | ||
|
||
try { | ||
// retrieve service details from data store | ||
$accounts = $this->accountService->findByUserIdAndAddress($userId, $address); | ||
} catch(\Throwable $th) { | ||
return null; | ||
} | ||
// evaliate if service details where found | ||
if (is_array($accounts) && count($accounts) > 0 && $accounts[0] instanceof Account) { | ||
// extract values | ||
$serviceId = (string) $accounts[0]->getId(); | ||
$label = $accounts[0]->getName(); | ||
$address = new MailAddress($accounts[0]->getEmail(), $accounts[0]->getName()); | ||
// return mail service object | ||
return new MailService($this->container, $userId, $serviceId, $label, $address); | ||
} | ||
|
||
return null; | ||
|
||
} | ||
|
||
/** | ||
* construct a new empty service object | ||
* | ||
* @since 30.0.0 | ||
* | ||
* @return IService blank service object | ||
*/ | ||
public function initiateService(): IService { | ||
|
||
return new MailService($this->container); | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.