mirror of
https://github.com/nextcloud/server.git
synced 2026-04-15 22:11:17 -04:00
feat: mail provider backend
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
This commit is contained in:
parent
f9d4becf60
commit
fc0b694d37
25 changed files with 2320 additions and 31 deletions
|
|
@ -15,6 +15,8 @@ use OCP\Defaults;
|
|||
use OCP\IConfig;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\Mail\Provider\IManager as IMailManager;
|
||||
use OCP\Mail\Provider\IMessageSend;
|
||||
use OCP\Util;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sabre\CalDAV\Schedule\IMipPlugin as SabreIMipPlugin;
|
||||
|
|
@ -55,6 +57,7 @@ class IMipPlugin extends SabreIMipPlugin {
|
|||
public const METHOD_CANCEL = 'cancel';
|
||||
public const IMIP_INDENT = 15; // Enough for the length of all body bullet items, in all languages
|
||||
private EventComparisonService $eventComparisonService;
|
||||
private IMailManager $mailManager;
|
||||
|
||||
public function __construct(IConfig $config,
|
||||
IMailer $mailer,
|
||||
|
|
@ -63,7 +66,8 @@ class IMipPlugin extends SabreIMipPlugin {
|
|||
Defaults $defaults,
|
||||
IUserSession $userSession,
|
||||
IMipService $imipService,
|
||||
EventComparisonService $eventComparisonService) {
|
||||
EventComparisonService $eventComparisonService,
|
||||
IMailManager $mailManager) {
|
||||
parent::__construct('');
|
||||
$this->userSession = $userSession;
|
||||
$this->config = $config;
|
||||
|
|
@ -73,6 +77,7 @@ class IMipPlugin extends SabreIMipPlugin {
|
|||
$this->defaults = $defaults;
|
||||
$this->imipService = $imipService;
|
||||
$this->eventComparisonService = $eventComparisonService;
|
||||
$this->mailManager = $mailManager;
|
||||
}
|
||||
|
||||
public function initialize(DAV\Server $server): void {
|
||||
|
|
@ -212,21 +217,6 @@ class IMipPlugin extends SabreIMipPlugin {
|
|||
$fromEMail = Util::getDefaultEmailAddress('invitations-noreply');
|
||||
$fromName = $this->imipService->getFrom($senderName, $this->defaults->getName());
|
||||
|
||||
$message = $this->mailer->createMessage()
|
||||
->setFrom([$fromEMail => $fromName]);
|
||||
|
||||
if ($recipientName !== null) {
|
||||
$message->setTo([$recipient => $recipientName]);
|
||||
} else {
|
||||
$message->setTo([$recipient]);
|
||||
}
|
||||
|
||||
if ($senderName !== null) {
|
||||
$message->setReplyTo([$sender => $senderName]);
|
||||
} else {
|
||||
$message->setReplyTo([$sender]);
|
||||
}
|
||||
|
||||
$template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
|
||||
$template->addHeader();
|
||||
|
||||
|
|
@ -268,18 +258,60 @@ class IMipPlugin extends SabreIMipPlugin {
|
|||
}
|
||||
|
||||
$template->addFooter();
|
||||
|
||||
$message->useTemplate($template);
|
||||
|
||||
// convert iTip Message to string
|
||||
$itip_msg = $iTipMessage->message->serialize();
|
||||
$message->attachInline(
|
||||
$itip_msg,
|
||||
'event.ics',
|
||||
'text/calendar; method=' . $iTipMessage->method,
|
||||
);
|
||||
|
||||
$user = null;
|
||||
$mailService = null;
|
||||
|
||||
try {
|
||||
$failed = $this->mailer->send($message);
|
||||
// retrieve user object
|
||||
$user = $this->userSession->getUser();
|
||||
// evaluate if user object exist
|
||||
if ($user !== null) {
|
||||
// retrieve appropriate service with the same address as sender
|
||||
$mailService = $this->mailManager->findServiceByAddress($user->getUID(), $sender);
|
||||
}
|
||||
// evaluate if a mail service was found and has sending capabilities
|
||||
if ($mailService !== null && $mailService instanceof IMessageSend) {
|
||||
// construct mail message and set required parameters
|
||||
$message = $mailService->initiateMessage();
|
||||
$message->setFrom(
|
||||
(new \OCP\Mail\Provider\Address($sender, $fromName))
|
||||
);
|
||||
$message->setTo(
|
||||
(new \OCP\Mail\Provider\Address($recipient, $recipientName))
|
||||
);
|
||||
$message->setSubject($template->renderSubject());
|
||||
$message->setBodyPlain($template->renderText());
|
||||
$message->setBodyHtml($template->renderHtml());
|
||||
$message->setAttachments((new \OCP\Mail\Provider\Attachment(
|
||||
$itip_msg,
|
||||
'event.ics',
|
||||
'text/calendar; method=' . $iTipMessage->method,
|
||||
true
|
||||
)));
|
||||
// send message
|
||||
$mailService->sendMessage($message);
|
||||
} else {
|
||||
// construct symfony mailer message and set required parameters
|
||||
$message = $this->mailer->createMessage();
|
||||
$message->setFrom([$fromEMail => $fromName]);
|
||||
$message->setTo(
|
||||
(($recipientName !== null) ? [$recipient => $recipientName] : [$recipient])
|
||||
);
|
||||
$message->setReplyTo(
|
||||
(($senderName !== null) ? [$sender => $senderName] : [$sender])
|
||||
);
|
||||
$message->useTemplate($template);
|
||||
$message->attachInline(
|
||||
$itip_msg,
|
||||
'event.ics',
|
||||
'text/calendar; method=' . $iTipMessage->method
|
||||
);
|
||||
$failed = $this->mailer->send($message);
|
||||
}
|
||||
|
||||
$iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
|
||||
if (!empty($failed)) {
|
||||
$this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' => implode(', ', $failed)]);
|
||||
|
|
|
|||
|
|
@ -292,7 +292,8 @@ class Server {
|
|||
\OC::$server->get(\OCP\Defaults::class),
|
||||
$userSession,
|
||||
\OC::$server->get(\OCA\DAV\CalDAV\Schedule\IMipService::class),
|
||||
\OC::$server->get(\OCA\DAV\CalDAV\EventComparisonService::class)
|
||||
\OC::$server->get(\OCA\DAV\CalDAV\EventComparisonService::class),
|
||||
\OC::$server->get(\OCP\Mail\Provider\IManager::class)
|
||||
));
|
||||
}
|
||||
$this->server->addPlugin(new \OCA\DAV\CalDAV\Search\SearchPlugin());
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ use OCP\Mail\IAttachment;
|
|||
use OCP\Mail\IEMailTemplate;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\Mail\IMessage;
|
||||
use OCP\Mail\Provider\IManager as IMailManager;
|
||||
use OCP\Mail\Provider\IMessage as IMailMessageNew;
|
||||
use OCP\Mail\Provider\IMessageSend as IMailMessageSend;
|
||||
use OCP\Mail\Provider\IService as IMailService;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
|
|
@ -26,6 +30,11 @@ use Sabre\VObject\ITip\Message;
|
|||
use Test\TestCase;
|
||||
use function array_merge;
|
||||
|
||||
interface IMailServiceMock extends IMailService, IMailMessageSend {
|
||||
// workaround for creating mock class with multiple interfaces
|
||||
// TODO: remove after phpUnit 10 is supported.
|
||||
}
|
||||
|
||||
class IMipPluginTest extends TestCase {
|
||||
|
||||
/** @var IMessage|MockObject */
|
||||
|
|
@ -67,6 +76,15 @@ class IMipPluginTest extends TestCase {
|
|||
/** @var EventComparisonService|MockObject */
|
||||
private $eventComparisonService;
|
||||
|
||||
/** @var IMailManager|MockObject */
|
||||
private $mailManager;
|
||||
|
||||
/** @var IMailService|IMailMessageSend|MockObject */
|
||||
private $mailService;
|
||||
|
||||
/** @var IMailMessageNew|MockObject */
|
||||
private $mailMessageNew;
|
||||
|
||||
protected function setUp(): void {
|
||||
$this->mailMessage = $this->createMock(IMessage::class);
|
||||
$this->mailMessage->method('setFrom')->willReturn($this->mailMessage);
|
||||
|
|
@ -90,10 +108,6 @@ class IMipPluginTest extends TestCase {
|
|||
$this->config = $this->createMock(IConfig::class);
|
||||
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
/*
|
||||
$this->user->method('getUID');
|
||||
$this->user->method('getDisplayName');
|
||||
*/
|
||||
|
||||
$this->userSession = $this->createMock(IUserSession::class);
|
||||
$this->userSession->method('getUser')
|
||||
|
|
@ -107,6 +121,12 @@ class IMipPluginTest extends TestCase {
|
|||
|
||||
$this->eventComparisonService = $this->createMock(EventComparisonService::class);
|
||||
|
||||
$this->mailManager = $this->createMock(IMailManager::class);
|
||||
|
||||
$this->mailService = $this->createMock(IMailServiceMock::class);
|
||||
|
||||
$this->mailMessageNew = $this->createMock(IMailMessageNew::class);
|
||||
|
||||
$this->plugin = new IMipPlugin(
|
||||
$this->config,
|
||||
$this->mailer,
|
||||
|
|
@ -115,7 +135,8 @@ class IMipPluginTest extends TestCase {
|
|||
$this->defaults,
|
||||
$this->userSession,
|
||||
$this->service,
|
||||
$this->eventComparisonService
|
||||
$this->eventComparisonService,
|
||||
$this->mailManager,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -582,6 +603,111 @@ class IMipPluginTest extends TestCase {
|
|||
$this->assertEquals('5.0', $message->getScheduleStatus());
|
||||
}
|
||||
|
||||
public function testMailProviderSend(): void {
|
||||
// construct iTip message with event and attendees
|
||||
$message = new Message();
|
||||
$message->method = 'REQUEST';
|
||||
$calendar = new VCalendar();
|
||||
$event = new VEvent($calendar, 'one', array_merge([
|
||||
'UID' => 'uid-1234',
|
||||
'SEQUENCE' => 1,
|
||||
'SUMMARY' => 'Fellowship meeting without (!) Boromir',
|
||||
'DTSTART' => new \DateTime('2016-01-01 00:00:00')
|
||||
], []));
|
||||
$event->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
|
||||
$event->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']);
|
||||
$message->message = $calendar;
|
||||
$message->sender = 'mailto:gandalf@wiz.ard';
|
||||
$message->senderName = 'Mr. Wizard';
|
||||
$message->recipient = 'mailto:' . 'frodo@hobb.it';
|
||||
// construct
|
||||
foreach ($event->select('ATTENDEE') as $entry) {
|
||||
if (strcasecmp($entry->getValue(), $message->recipient) === 0) {
|
||||
$attendee = $entry;
|
||||
}
|
||||
}
|
||||
// construct body data return
|
||||
$data = ['invitee_name' => 'Mr. Wizard',
|
||||
'meeting_title' => 'Fellowship meeting without (!) Boromir',
|
||||
'attendee_name' => 'frodo@hobb.it'
|
||||
];
|
||||
// construct system config mock returns
|
||||
$this->config->expects(self::once())
|
||||
->method('getAppValue')
|
||||
->with('dav', 'invitation_link_recipients', 'yes')
|
||||
->willReturn('yes');
|
||||
// construct user mock returns
|
||||
$this->user->expects(self::any())
|
||||
->method('getUID')
|
||||
->willReturn('user1');
|
||||
$this->user->expects(self::any())
|
||||
->method('getDisplayName')
|
||||
->willReturn('Mr. Wizard');
|
||||
// construct user session mock returns
|
||||
$this->userSession->expects(self::any())
|
||||
->method('getUser')
|
||||
->willReturn($this->user);
|
||||
// construct service mock returns
|
||||
$this->service->expects(self::once())
|
||||
->method('getLastOccurrence')
|
||||
->willReturn('1496912700');
|
||||
$this->service->expects(self::once())
|
||||
->method('getCurrentAttendee')
|
||||
->with($message)
|
||||
->willReturn($attendee);
|
||||
$this->service->expects(self::once())
|
||||
->method('isRoomOrResource')
|
||||
->with($attendee)
|
||||
->willReturn(false);
|
||||
$this->service->expects(self::once())
|
||||
->method('buildBodyData')
|
||||
->with($event, null)
|
||||
->willReturn($data);
|
||||
$this->service->expects(self::once())
|
||||
->method('getFrom');
|
||||
$this->service->expects(self::once())
|
||||
->method('addSubjectAndHeading')
|
||||
->with($this->emailTemplate, 'request', 'Mr. Wizard', 'Fellowship meeting without (!) Boromir', false);
|
||||
$this->service->expects(self::once())
|
||||
->method('addBulletList')
|
||||
->with($this->emailTemplate, $event, $data);
|
||||
$this->service->expects(self::once())
|
||||
->method('getAttendeeRsvpOrReqForParticipant')
|
||||
->willReturn(true);
|
||||
$this->service->expects(self::once())
|
||||
->method('createInvitationToken')
|
||||
->with($message, $event, '1496912700')
|
||||
->willReturn('token');
|
||||
$this->service->expects(self::once())
|
||||
->method('addResponseButtons')
|
||||
->with($this->emailTemplate, 'token');
|
||||
$this->service->expects(self::once())
|
||||
->method('addMoreOptionsButton')
|
||||
->with($this->emailTemplate, 'token');
|
||||
$this->eventComparisonService->expects(self::once())
|
||||
->method('findModified')
|
||||
->willReturn(['old' => [] ,'new' => [$event]]);
|
||||
// construct mail mock returns
|
||||
$this->mailer->expects(self::once())
|
||||
->method('validateMailAddress')
|
||||
->with('frodo@hobb.it')
|
||||
->willReturn(true);
|
||||
// construct mail provider mock returns
|
||||
$this->mailService
|
||||
->method('initiateMessage')
|
||||
->willReturn($this->mailMessageNew);
|
||||
$this->mailService
|
||||
->method('sendMessage')
|
||||
->with($this->mailMessageNew);
|
||||
$this->mailManager
|
||||
->method('findServiceByAddress')
|
||||
->with('user1', 'gandalf@wiz.ard')
|
||||
->willReturn($this->mailService);
|
||||
|
||||
$this->plugin->schedule($message);
|
||||
$this->assertEquals('1.1', $message->getScheduleStatus());
|
||||
}
|
||||
|
||||
public function testNoOldEvent(): void {
|
||||
$message = new Message();
|
||||
$message->method = 'REQUEST';
|
||||
|
|
|
|||
|
|
@ -568,6 +568,18 @@ return array(
|
|||
'OCP\\Mail\\IEMailTemplate' => $baseDir . '/lib/public/Mail/IEMailTemplate.php',
|
||||
'OCP\\Mail\\IMailer' => $baseDir . '/lib/public/Mail/IMailer.php',
|
||||
'OCP\\Mail\\IMessage' => $baseDir . '/lib/public/Mail/IMessage.php',
|
||||
'OCP\\Mail\\Provider\\Address' => $baseDir . '/lib/public/Mail/Provider/Address.php',
|
||||
'OCP\\Mail\\Provider\\Attachment' => $baseDir . '/lib/public/Mail/Provider/Attachment.php',
|
||||
'OCP\\Mail\\Provider\\Exception\\Exception' => $baseDir . '/lib/public/Mail/Provider/Exception/Exception.php',
|
||||
'OCP\\Mail\\Provider\\Exception\\SendException' => $baseDir . '/lib/public/Mail/Provider/Exception/SendException.php',
|
||||
'OCP\\Mail\\Provider\\IAddress' => $baseDir . '/lib/public/Mail/Provider/IAddress.php',
|
||||
'OCP\\Mail\\Provider\\IAttachment' => $baseDir . '/lib/public/Mail/Provider/IAttachment.php',
|
||||
'OCP\\Mail\\Provider\\IManager' => $baseDir . '/lib/public/Mail/Provider/IManager.php',
|
||||
'OCP\\Mail\\Provider\\IMessage' => $baseDir . '/lib/public/Mail/Provider/IMessage.php',
|
||||
'OCP\\Mail\\Provider\\IMessageSend' => $baseDir . '/lib/public/Mail/Provider/IMessageSend.php',
|
||||
'OCP\\Mail\\Provider\\IProvider' => $baseDir . '/lib/public/Mail/Provider/IProvider.php',
|
||||
'OCP\\Mail\\Provider\\IService' => $baseDir . '/lib/public/Mail/Provider/IService.php',
|
||||
'OCP\\Mail\\Provider\\Message' => $baseDir . '/lib/public/Mail/Provider/Message.php',
|
||||
'OCP\\Migration\\BigIntMigration' => $baseDir . '/lib/public/Migration/BigIntMigration.php',
|
||||
'OCP\\Migration\\IMigrationStep' => $baseDir . '/lib/public/Migration/IMigrationStep.php',
|
||||
'OCP\\Migration\\IOutput' => $baseDir . '/lib/public/Migration/IOutput.php',
|
||||
|
|
@ -1618,6 +1630,7 @@ return array(
|
|||
'OC\\Mail\\EMailTemplate' => $baseDir . '/lib/private/Mail/EMailTemplate.php',
|
||||
'OC\\Mail\\Mailer' => $baseDir . '/lib/private/Mail/Mailer.php',
|
||||
'OC\\Mail\\Message' => $baseDir . '/lib/private/Mail/Message.php',
|
||||
'OC\\Mail\\Provider\\Manager' => $baseDir . '/lib/private/Mail/Provider/Manager.php',
|
||||
'OC\\Memcache\\APCu' => $baseDir . '/lib/private/Memcache/APCu.php',
|
||||
'OC\\Memcache\\ArrayCache' => $baseDir . '/lib/private/Memcache/ArrayCache.php',
|
||||
'OC\\Memcache\\CADTrait' => $baseDir . '/lib/private/Memcache/CADTrait.php',
|
||||
|
|
|
|||
|
|
@ -601,6 +601,18 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\Mail\\IEMailTemplate' => __DIR__ . '/../../..' . '/lib/public/Mail/IEMailTemplate.php',
|
||||
'OCP\\Mail\\IMailer' => __DIR__ . '/../../..' . '/lib/public/Mail/IMailer.php',
|
||||
'OCP\\Mail\\IMessage' => __DIR__ . '/../../..' . '/lib/public/Mail/IMessage.php',
|
||||
'OCP\\Mail\\Provider\\Address' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/Address.php',
|
||||
'OCP\\Mail\\Provider\\Attachment' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/Attachment.php',
|
||||
'OCP\\Mail\\Provider\\Exception\\Exception' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/Exception/Exception.php',
|
||||
'OCP\\Mail\\Provider\\Exception\\SendException' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/Exception/SendException.php',
|
||||
'OCP\\Mail\\Provider\\IAddress' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IAddress.php',
|
||||
'OCP\\Mail\\Provider\\IAttachment' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IAttachment.php',
|
||||
'OCP\\Mail\\Provider\\IManager' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IManager.php',
|
||||
'OCP\\Mail\\Provider\\IMessage' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IMessage.php',
|
||||
'OCP\\Mail\\Provider\\IMessageSend' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IMessageSend.php',
|
||||
'OCP\\Mail\\Provider\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IProvider.php',
|
||||
'OCP\\Mail\\Provider\\IService' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/IService.php',
|
||||
'OCP\\Mail\\Provider\\Message' => __DIR__ . '/../../..' . '/lib/public/Mail/Provider/Message.php',
|
||||
'OCP\\Migration\\BigIntMigration' => __DIR__ . '/../../..' . '/lib/public/Migration/BigIntMigration.php',
|
||||
'OCP\\Migration\\IMigrationStep' => __DIR__ . '/../../..' . '/lib/public/Migration/IMigrationStep.php',
|
||||
'OCP\\Migration\\IOutput' => __DIR__ . '/../../..' . '/lib/public/Migration/IOutput.php',
|
||||
|
|
@ -1651,6 +1663,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OC\\Mail\\EMailTemplate' => __DIR__ . '/../../..' . '/lib/private/Mail/EMailTemplate.php',
|
||||
'OC\\Mail\\Mailer' => __DIR__ . '/../../..' . '/lib/private/Mail/Mailer.php',
|
||||
'OC\\Mail\\Message' => __DIR__ . '/../../..' . '/lib/private/Mail/Message.php',
|
||||
'OC\\Mail\\Provider\\Manager' => __DIR__ . '/../../..' . '/lib/private/Mail/Provider/Manager.php',
|
||||
'OC\\Memcache\\APCu' => __DIR__ . '/../../..' . '/lib/private/Memcache/APCu.php',
|
||||
'OC\\Memcache\\ArrayCache' => __DIR__ . '/../../..' . '/lib/private/Memcache/ArrayCache.php',
|
||||
'OC\\Memcache\\CADTrait' => __DIR__ . '/../../..' . '/lib/private/Memcache/CADTrait.php',
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use OCP\Dashboard\IWidget;
|
|||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Template\ICustomTemplateProvider;
|
||||
use OCP\Http\WellKnown\IHandler;
|
||||
use OCP\Mail\Provider\IProvider as IMailProvider;
|
||||
use OCP\Notification\INotifier;
|
||||
use OCP\Profile\ILinkAction;
|
||||
use OCP\Search\IProvider;
|
||||
|
|
@ -148,6 +149,9 @@ class RegistrationContext {
|
|||
|
||||
/** @var ServiceRegistration<\OCP\TaskProcessing\ITaskType>[] */
|
||||
private array $taskProcessingTaskTypes = [];
|
||||
|
||||
/** @var ServiceRegistration<IMailProvider>[] */
|
||||
private $mailProviders = [];
|
||||
|
||||
public function __construct(LoggerInterface $logger) {
|
||||
$this->logger = $logger;
|
||||
|
|
@ -411,6 +415,13 @@ class RegistrationContext {
|
|||
$taskProcessingTaskTypeClass
|
||||
);
|
||||
}
|
||||
|
||||
public function registerMailProvider(string $class): void {
|
||||
$this->context->registerMailProvider(
|
||||
$this->appId,
|
||||
$class
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -603,6 +614,12 @@ class RegistrationContext {
|
|||
public function registerTaskProcessingTaskType(string $appId, string $taskProcessingTaskTypeClass) {
|
||||
$this->taskProcessingTaskTypes[] = new ServiceRegistration($appId, $taskProcessingTaskTypeClass);
|
||||
}
|
||||
/**
|
||||
* @psalm-param class-string<IMailProvider> $migratorClass
|
||||
*/
|
||||
public function registerMailProvider(string $appId, string $class): void {
|
||||
$this->mailProviders[] = new ServiceRegistration($appId, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param App[] $apps
|
||||
|
|
@ -948,4 +965,11 @@ class RegistrationContext {
|
|||
public function getTaskProcessingTaskTypes(): array {
|
||||
return $this->taskProcessingTaskTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ServiceRegistration<IMailProvider>[]
|
||||
*/
|
||||
public function getMailProviders(): array {
|
||||
return $this->mailProviders;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
255
lib/private/Mail/Provider/Manager.php
Normal file
255
lib/private/Mail/Provider/Manager.php
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OC\Mail\Provider;
|
||||
|
||||
use OC\AppFramework\Bootstrap\Coordinator;
|
||||
use OCP\Mail\Provider\IManager;
|
||||
use OCP\Mail\Provider\IProvider;
|
||||
use OCP\Mail\Provider\IService;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Throwable;
|
||||
|
||||
class Manager implements IManager {
|
||||
|
||||
protected ?array $providersCollection = null;
|
||||
|
||||
public function __construct(
|
||||
private Coordinator $coordinator,
|
||||
private ContainerInterface $container,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any mail providers are registered
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(): bool {
|
||||
|
||||
// return true if collection has any providers
|
||||
return !empty($this->providers());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a count of how many mail providers are registered
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int {
|
||||
|
||||
// return count of providers in collection
|
||||
return count($this->providers());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve which mail providers are registered
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<string,string> collection of provider id and label ['jmap' => 'JMap Connector']
|
||||
*/
|
||||
public function types(): array {
|
||||
|
||||
// construct types collection
|
||||
$types = [];
|
||||
// extract id and name from providers collection
|
||||
foreach ($this->providers() as $entry) {
|
||||
$types[$entry->id()] = $entry->label();
|
||||
}
|
||||
// return types collection
|
||||
return $types;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all registered mail providers
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<string,IProvider> collection of provider id and object ['jmap' => IProviderObject]
|
||||
*/
|
||||
public function providers(): array {
|
||||
|
||||
// evaluate if we already have a cached collection of providers and return the collection if we do
|
||||
if (is_array($this->providersCollection)) {
|
||||
return $this->providersCollection;
|
||||
}
|
||||
// retrieve server registration context
|
||||
$context = $this->coordinator->getRegistrationContext();
|
||||
// evaluate if registration context was returned
|
||||
if ($context === null) {
|
||||
return [];
|
||||
}
|
||||
// initilize cached collection
|
||||
$this->providersCollection = [];
|
||||
// iterate through all registered mail providers
|
||||
foreach ($context->getMailProviders() as $entry) {
|
||||
try {
|
||||
/** @var IProvider $provider */
|
||||
// object provider
|
||||
$provider = $this->container->get($entry->getService());
|
||||
// add provider to cache collection
|
||||
$this->providersCollection[$provider->id()] = $provider;
|
||||
} catch (Throwable $e) {
|
||||
$this->logger->error(
|
||||
'Could not load mail provider ' . $entry->getService() . ': ' . $e->getMessage(),
|
||||
['exception' => $e]
|
||||
);
|
||||
}
|
||||
}
|
||||
// return mail provider collection
|
||||
return $this->providersCollection;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a provider with a specific id
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $providerId provider id
|
||||
*
|
||||
* @return IProvider|null
|
||||
*/
|
||||
public function findProviderById(string $providerId): IProvider | null {
|
||||
|
||||
// evaluate if we already have a cached collection of providers
|
||||
if (!is_array($this->providersCollection)) {
|
||||
$this->providers();
|
||||
}
|
||||
|
||||
if (isset($this->providersCollection[$providerId])) {
|
||||
return $this->providersCollection[$providerId];
|
||||
}
|
||||
// return null if provider was not found
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all services for all registered mail providers
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
*
|
||||
* @return array<string,array<string,IService>> collection of provider id, service id and object ['jmap' => ['Service1' => IServiceObject]]
|
||||
*/
|
||||
public function services(string $userId): array {
|
||||
|
||||
// initilize collection
|
||||
$services = [];
|
||||
// retrieve and iterate through mail providers
|
||||
foreach ($this->providers() as $entry) {
|
||||
// retrieve collection of services
|
||||
$mailServices = $entry->listServices($userId);
|
||||
// evaluate if mail services collection is not empty and add results to services collection
|
||||
if (!empty($mailServices)) {
|
||||
$services[$entry->id()] = $mailServices;
|
||||
}
|
||||
}
|
||||
// return collection
|
||||
return $services;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a service with a specific id
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
* @param string $serviceId service id
|
||||
* @param string $providerId provider id
|
||||
*
|
||||
* @return IService|null returns service object or null if none found
|
||||
*/
|
||||
public function findServiceById(string $userId, string $serviceId, ?string $providerId = null): IService | null {
|
||||
|
||||
// evaluate if provider id was specified
|
||||
if ($providerId !== null) {
|
||||
// find provider
|
||||
$provider = $this->findProviderById($providerId);
|
||||
// evaluate if provider was found
|
||||
if ($provider instanceof IProvider) {
|
||||
// find service with specific id
|
||||
$service = $provider->findServiceById($userId, $serviceId);
|
||||
// evaluate if mail service was found
|
||||
if ($service instanceof IService) {
|
||||
return $service;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// retrieve and iterate through mail providers
|
||||
foreach ($this->providers() as $provider) {
|
||||
// find service with specific id
|
||||
$service = $provider->findServiceById($userId, $serviceId);
|
||||
// evaluate if mail service was found
|
||||
if ($service instanceof IService) {
|
||||
return $service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return null if no match was found
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a service for a specific mail address
|
||||
* returns first service with specific primary address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
* @param string $address mail address (e.g. test@example.com)
|
||||
* @param string $providerId provider id
|
||||
*
|
||||
* @return IService|null returns service object or null if none found
|
||||
*/
|
||||
public function findServiceByAddress(string $userId, string $address, ?string $providerId = null): IService | null {
|
||||
|
||||
// evaluate if provider id was specified
|
||||
if ($providerId !== null) {
|
||||
// find provider
|
||||
$provider = $this->findProviderById($providerId);
|
||||
// evaluate if provider was found
|
||||
if ($provider instanceof IProvider) {
|
||||
// find service with specific mail address
|
||||
$service = $provider->findServiceByAddress($userId, $address);
|
||||
// evaluate if mail service was found
|
||||
if ($service instanceof IService) {
|
||||
return $service;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// retrieve and iterate through mail providers
|
||||
foreach ($this->providers() as $provider) {
|
||||
// find service with specific mail address
|
||||
$service = $provider->findServiceByAddress($userId, $address);
|
||||
// evaluate if mail service was found
|
||||
if ($service instanceof IService) {
|
||||
return $service;
|
||||
}
|
||||
}
|
||||
}
|
||||
// return null if no match was found
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1026,6 +1026,9 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
/** @deprecated 19.0.0 */
|
||||
$this->registerDeprecatedAlias('Mailer', IMailer::class);
|
||||
|
||||
/** @since 30.0.0 */
|
||||
$this->registerAlias(\OCP\Mail\Provider\IManager::class, \OC\Mail\Provider\Manager::class);
|
||||
|
||||
/** @deprecated 21.0.0 */
|
||||
$this->registerDeprecatedAlias('LDAPProvider', ILDAPProvider::class);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use OCP\Collaboration\Reference\IReferenceProvider;
|
|||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Template\ICustomTemplateProvider;
|
||||
use OCP\IContainer;
|
||||
use OCP\Mail\Provider\IProvider as IMailProvider;
|
||||
use OCP\Notification\INotifier;
|
||||
use OCP\Preview\IProviderV2;
|
||||
use OCP\SpeechToText\ISpeechToTextProvider;
|
||||
|
|
@ -412,4 +413,14 @@ interface IRegistrationContext {
|
|||
* @since 30.0.0
|
||||
*/
|
||||
public function registerTaskProcessingTaskType(string $taskProcessingTaskTypeClass): void;
|
||||
|
||||
/**
|
||||
* Register a mail provider
|
||||
*
|
||||
* @param string $class
|
||||
* @psalm-param class-string<IMailProvider> $class
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function registerMailProvider(string $class): void;
|
||||
|
||||
}
|
||||
|
|
|
|||
85
lib/public/Mail/Provider/Address.php
Normal file
85
lib/public/Mail/Provider/Address.php
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Address Object
|
||||
*
|
||||
* This object is used to define the address and label of a email address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
class Address implements \OCP\Mail\Provider\IAddress {
|
||||
|
||||
/**
|
||||
* initialize the mail address object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null $address mail address (e.g test@example.com)
|
||||
* @param string|null $label mail address label/name
|
||||
*/
|
||||
public function __construct(
|
||||
protected ?string $address = null,
|
||||
protected ?string $label = null
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the mail address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value mail address (e.g. test@example.com)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setAddress(string $value): self {
|
||||
$this->address = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the mail address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string|null returns the mail address or null if one is not set
|
||||
*/
|
||||
public function getAddress(): string | null {
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the mail address label/name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value mail address label/name
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setLabel(string $value): self {
|
||||
$this->label = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the mail address label/name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string|null returns the mail address label/name or null if one is not set
|
||||
*/
|
||||
public function getLabel(): string | null {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
}
|
||||
139
lib/public/Mail/Provider/Attachment.php
Normal file
139
lib/public/Mail/Provider/Attachment.php
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Attachment Object
|
||||
*
|
||||
* This object is used to define the parameters of a mail attachment
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
class Attachment implements \OCP\Mail\Provider\IAttachment {
|
||||
|
||||
/**
|
||||
* initialize the mail attachment object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null $contents binary contents of file
|
||||
* @param string|null $name file name (e.g example.txt)
|
||||
* @param string|null $type mime type (e.g. text/plain)
|
||||
* @param bool $embedded embedded status of the attachment, default is false
|
||||
*/
|
||||
public function __construct(
|
||||
protected ?string $contents,
|
||||
protected ?string $name,
|
||||
protected ?string $type,
|
||||
protected bool $embedded = false
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the attachment file name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value file name (e.g example.txt)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setName(string $value): self {
|
||||
$this->name = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the attachment file name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string | null returns the attachment file name or null if not set
|
||||
*/
|
||||
public function getName(): string | null {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the attachment mime type
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value mime type (e.g. text/plain)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setType(string $value): self {
|
||||
$this->type = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the attachment mime type
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string | null returns the attachment mime type or null if not set
|
||||
*/
|
||||
public function getType(): string | null {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the attachment contents (actual data)
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value binary contents of file
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setContents(string $value): self {
|
||||
$this->contents = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the attachment contents (actual data)
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string | null returns the attachment contents or null if not set
|
||||
*/
|
||||
public function getContents(): string | null {
|
||||
return $this->contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the embedded status of the attachment
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param bool $value true - embedded / false - not embedded
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setEmbedded(bool $value): self {
|
||||
$this->embedded = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the embedded status of the attachment
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return bool embedded status of the attachment
|
||||
*/
|
||||
public function getEmbedded(): bool {
|
||||
return $this->embedded;
|
||||
}
|
||||
|
||||
}
|
||||
18
lib/public/Mail/Provider/Exception/Exception.php
Normal file
18
lib/public/Mail/Provider/Exception/Exception.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider\Exception;
|
||||
|
||||
/**
|
||||
* Mail Provider Base Exception
|
||||
*
|
||||
* @since 30.0.0
|
||||
*/
|
||||
class Exception extends \Exception {
|
||||
|
||||
}
|
||||
18
lib/public/Mail/Provider/Exception/SendException.php
Normal file
18
lib/public/Mail/Provider/Exception/SendException.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider\Exception;
|
||||
|
||||
/**
|
||||
* Mail Provider Send Exception
|
||||
*
|
||||
* @since 30.0.0
|
||||
*/
|
||||
class SendException extends Exception {
|
||||
|
||||
}
|
||||
61
lib/public/Mail/Provider/IAddress.php
Normal file
61
lib/public/Mail/Provider/IAddress.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Address Interface
|
||||
*
|
||||
* This interface is a base requirement of methods and functionality used to construct a mail address object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IAddress {
|
||||
|
||||
/**
|
||||
* sets the mail address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value mail address (test@example.com)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setAddress(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the mail address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string returns the mail address
|
||||
*/
|
||||
public function getAddress(): string | null;
|
||||
|
||||
/**
|
||||
* sets the mail address label/name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value mail address label/name
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setLabel(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the mail address label/name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string returns the mail address label/name
|
||||
*/
|
||||
public function getLabel(): string | null;
|
||||
|
||||
}
|
||||
101
lib/public/Mail/Provider/IAttachment.php
Normal file
101
lib/public/Mail/Provider/IAttachment.php
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Attachment Interface
|
||||
*
|
||||
* This interface is used for defining individual attachments that are attached to a message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IAttachment {
|
||||
|
||||
/**
|
||||
* sets the attachment file name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value file name (e.g example.txt)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setName(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the attachment file name
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string | null returns the attachment file name or null if one is not set
|
||||
*/
|
||||
public function getName(): string | null;
|
||||
|
||||
/**
|
||||
* sets the attachment mime type
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value mime type (e.g. text/plain)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setType(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the attachment mime type
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string | null returns the attachment mime type or null if not set
|
||||
*/
|
||||
public function getType(): string | null;
|
||||
|
||||
/**
|
||||
* sets the attachment contents (actual data)
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value binary contents of file
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setContents(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the attachment contents (actual data)
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string | null returns the attachment contents or null if not set
|
||||
*/
|
||||
public function getContents(): string | null;
|
||||
|
||||
/**
|
||||
* sets the embedded status of the attachment
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param bool $value true - embedded / false - not embedded
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setEmbedded(bool $value): self;
|
||||
|
||||
/**
|
||||
* gets the embedded status of the attachment
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return bool embedded status of the attachment
|
||||
*/
|
||||
public function getEmbedded(): bool;
|
||||
|
||||
}
|
||||
106
lib/public/Mail/Provider/IManager.php
Normal file
106
lib/public/Mail/Provider/IManager.php
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Provider Manager Interface
|
||||
*
|
||||
* This interface is a base requirement of methods and functionality used to construct a mail provider manager object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IManager {
|
||||
|
||||
/**
|
||||
* determine if any mail providers are registered
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(): bool;
|
||||
|
||||
/**
|
||||
* retrieve a count of how many mail providers are registered
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int;
|
||||
|
||||
/**
|
||||
* retrieve which mail providers are registered
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<string,String> collection of provider id and label ['jmap' => 'JMap Connector']
|
||||
*/
|
||||
public function types(): array;
|
||||
|
||||
/**
|
||||
* retrieve all registered mail providers
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<string,IProvider> collection of provider id and object ['jmap' => IProviderObject]
|
||||
*/
|
||||
public function providers(): array;
|
||||
|
||||
/**
|
||||
* retrieve a provider with a specific id
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $providerId provider id
|
||||
*
|
||||
* @return IProvider|null
|
||||
*/
|
||||
public function findProviderById(string $providerId): IProvider | null;
|
||||
|
||||
/**
|
||||
* retrieve all services for all registered mail providers
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
*
|
||||
* @return array<string,array<string,IService>> collection of provider id, service id and object ['jmap' => ['Service1' => IServiceObject]]
|
||||
*/
|
||||
public function services(string $userId): array;
|
||||
|
||||
/**
|
||||
* retrieve a service with a specific id
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
* @param string $serviceId service id
|
||||
* @param string $providerId provider id
|
||||
*
|
||||
* @return IService|null returns service object or null if none found
|
||||
*/
|
||||
public function findServiceById(string $userId, string $serviceId, ?string $providerId = null): IService | null;
|
||||
|
||||
/**
|
||||
* retrieve a service for a specific mail address
|
||||
* returns first service with specific primary address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
* @param string $address mail address (e.g. test@example.com)
|
||||
* @param string $providerId provider id
|
||||
*
|
||||
* @return IService|null returns service object or null if none found
|
||||
*/
|
||||
public function findServiceByAddress(string $userId, string $address, ?string $providerId = null): IService | null;
|
||||
|
||||
}
|
||||
232
lib/public/Mail/Provider/IMessage.php
Normal file
232
lib/public/Mail/Provider/IMessage.php
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Message Interface
|
||||
*
|
||||
* This interface is a base requirement of methods and functionality used to construct a mail message object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IMessage {
|
||||
|
||||
/**
|
||||
* arbitrary unique text string identifying this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string id of this message
|
||||
*/
|
||||
public function id(): string;
|
||||
|
||||
/**
|
||||
* sets the sender of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress $value sender's mail address object
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setFrom(IAddress $value): self;
|
||||
|
||||
/**
|
||||
* gets the sender of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress|null sender's mail address object
|
||||
*/
|
||||
public function getFrom(): IAddress | null;
|
||||
|
||||
/**
|
||||
* sets the sender's reply to address of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress $value senders's reply to mail address object
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setReplyTo(IAddress $value): self;
|
||||
|
||||
/**
|
||||
* gets the sender's reply to address of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress|null sender's reply to mail address object
|
||||
*/
|
||||
public function getReplyTo(): IAddress | null;
|
||||
|
||||
/**
|
||||
* sets the recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of or one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setTo(IAddress ...$value): self;
|
||||
|
||||
/**
|
||||
* gets the recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array<int,IAddress> collection of all recipient mail address objects
|
||||
*/
|
||||
public function getTo(): array;
|
||||
|
||||
/**
|
||||
* sets the copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of or one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setCc(IAddress ...$value): self;
|
||||
|
||||
/**
|
||||
* gets the copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array<int,IAddress> collection of all copied recipient mail address objects
|
||||
*/
|
||||
public function getCc(): array;
|
||||
|
||||
/**
|
||||
* sets the blind copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of or one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBcc(IAddress ...$value): self;
|
||||
|
||||
/**
|
||||
* gets the blind copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array<int,IAddress> collection of all blind copied recipient mail address objects
|
||||
*/
|
||||
public function getBcc(): array;
|
||||
|
||||
/**
|
||||
* sets the subject of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value subject of mail message
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setSubject(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the subject of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null subject of message or null if one is not set
|
||||
*/
|
||||
public function getSubject(): string | null;
|
||||
|
||||
/**
|
||||
* sets the plain text or html body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value text or html body of message
|
||||
* @param bool $html html flag - true for html
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBody(string $value, bool $html): self;
|
||||
|
||||
/**
|
||||
* gets either the html or plain text body of this message
|
||||
*
|
||||
* html body will be returned over plain text if html body exists
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null html/plain body of this message or null if one is not set
|
||||
*/
|
||||
public function getBody(): string | null;
|
||||
|
||||
/**
|
||||
* sets the html body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value html body of message
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBodyHtml(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the html body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null html body of this message or null if one is not set
|
||||
*/
|
||||
public function getBodyHtml(): string | null;
|
||||
|
||||
/**
|
||||
* sets the plain text body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value plain text body of message
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBodyPlain(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the plain text body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null plain text body of this message or null if one is not set
|
||||
*/
|
||||
public function getBodyPlain(): string | null;
|
||||
|
||||
/**
|
||||
* sets the attachments of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAttachment ...$value collection of or one or more mail attachment objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setAttachments(IAttachment ...$value): self;
|
||||
|
||||
/**
|
||||
* gets the attachments of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<int,IAttachment> collection of all mail attachment objects
|
||||
*/
|
||||
public function getAttachments(): array;
|
||||
}
|
||||
31
lib/public/Mail/Provider/IMessageSend.php
Normal file
31
lib/public/Mail/Provider/IMessageSend.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Message Send Interface
|
||||
*
|
||||
* This interface is the required set of methods and functionality used to extend IService with message sending functionality
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IMessageSend {
|
||||
|
||||
/**
|
||||
* send an outbound message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IMessage $message mail message object with all required parameters to send a message
|
||||
* @param array $options array of options reserved for future use
|
||||
*/
|
||||
public function sendMessage(IMessage $message, array $option = []): void;
|
||||
|
||||
}
|
||||
94
lib/public/Mail/Provider/IProvider.php
Normal file
94
lib/public/Mail/Provider/IProvider.php
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Provider Interface
|
||||
*
|
||||
* This interface is a base requirement of methods and functionality used to construct a mail provider object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IProvider {
|
||||
|
||||
/**
|
||||
* arbitrary unique text string identifying this provider
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string id of this provider (e.g. UUID or 'IMAP/SMTP' or anything else)
|
||||
*/
|
||||
public function id(): string;
|
||||
|
||||
/**
|
||||
* localized human friendly name of this provider
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string label/name of this provider (e.g. Plain Old IMAP/SMTP)
|
||||
*/
|
||||
public function label(): string;
|
||||
|
||||
/**
|
||||
* determine if any services are configured for a specific user
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
*
|
||||
* @return bool true if any services are configure for the user
|
||||
*/
|
||||
public function hasServices(string $userId): bool;
|
||||
|
||||
/**
|
||||
* retrieve collection of services for a specific user
|
||||
*
|
||||
* @param string $userId user id
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<string,IService> collection of service id and object ['1' => IServiceObject]
|
||||
*/
|
||||
public function listServices(string $userId): array;
|
||||
|
||||
/**
|
||||
* retrieve a service with a specific id
|
||||
*
|
||||
* @since 30.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;
|
||||
|
||||
/**
|
||||
* retrieve a service for a specific mail address
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $userId user id
|
||||
* @param string $address mail address (e.g. test@example.com)
|
||||
*
|
||||
* @return IService|null returns service object or null if none found
|
||||
*/
|
||||
public function findServiceByAddress(string $userId, string $address): IService | null;
|
||||
|
||||
/**
|
||||
* construct a new empty service object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return IService blank service object
|
||||
*/
|
||||
public function initiateService(): IService;
|
||||
|
||||
}
|
||||
119
lib/public/Mail/Provider/IService.php
Normal file
119
lib/public/Mail/Provider/IService.php
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Service Interface
|
||||
*
|
||||
* This interface is a base requirement of methods and functionality used to construct a mail service object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
interface IService {
|
||||
|
||||
/**
|
||||
* arbitrary unique text string identifying this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string id of this service (e.g. 1 or service1 or anything else)
|
||||
*/
|
||||
public function id(): string;
|
||||
|
||||
/**
|
||||
* checks if a service is able of performing an specific action
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param string $value required ability e.g. 'MessageSend'
|
||||
*
|
||||
* @return bool true/false if ability is supplied and found in collection
|
||||
*/
|
||||
public function capable(string $value): bool;
|
||||
|
||||
/**
|
||||
* retrieves a collection of what actions a service can perfrom
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @return array collection of abilities otherwise empty collection
|
||||
*/
|
||||
public function capabilities(): array;
|
||||
|
||||
/**
|
||||
* gets the localized human frendly name of this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string label/name of service (e.g. ACME Company Mail Service)
|
||||
*/
|
||||
public function getLabel(): string;
|
||||
|
||||
/**
|
||||
* sets the localized human frendly name of this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value label/name of service (e.g. ACME Company Mail Service)
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setLabel(string $value): self;
|
||||
|
||||
/**
|
||||
* gets the primary mailing address for this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return IAddress mail address object
|
||||
*/
|
||||
public function getPrimaryAddress(): IAddress;
|
||||
|
||||
/**
|
||||
* sets the primary mailing address for this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress $value mail address object
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setPrimaryAddress(IAddress $value): self;
|
||||
|
||||
/**
|
||||
* gets the secondary mailing addresses (aliases) collection for this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<int, IAddress> collection of mail address objects
|
||||
*/
|
||||
public function getSecondaryAddresses(): array;
|
||||
|
||||
/**
|
||||
* sets the secondary mailing addresses (aliases) for this service
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setSecondaryAddresses(IAddress ...$value): self;
|
||||
|
||||
/**
|
||||
* construct a new empty message object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return IMessage blank message object
|
||||
*/
|
||||
public function initiateMessage(): IMessage;
|
||||
|
||||
}
|
||||
338
lib/public/Mail/Provider/Message.php
Normal file
338
lib/public/Mail/Provider/Message.php
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Mail\Provider;
|
||||
|
||||
/**
|
||||
* Mail Message Object
|
||||
*
|
||||
* This object is used to define a mail message that can be used to transfer data to a provider
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
*/
|
||||
class Message implements \OCP\Mail\Provider\IMessage {
|
||||
|
||||
/**
|
||||
* initialize the mail message object
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array $data message data array
|
||||
*/
|
||||
public function __construct(
|
||||
protected array $data = [],
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* arbitrary unique text string identifying this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return string id of this message
|
||||
*/
|
||||
public function id(): string {
|
||||
// return id of message
|
||||
return (isset($this->data['id'])) ? $this->data['id'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the sender of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress $value sender's mail address object
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setFrom(IAddress $value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['from'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the sender of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress|null sender's mail address object
|
||||
*/
|
||||
public function getFrom(): IAddress | null {
|
||||
// evaluate if data store field exists and return value(s) or null otherwise
|
||||
return (isset($this->data['from'])) ? $this->data['from'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the sender's reply to address of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress $value senders's reply to mail address object
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setReplyTo(IAddress $value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['replyTo'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the sender's reply to address of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress|null sender's reply to mail address object
|
||||
*/
|
||||
public function getReplyTo(): IAddress | null {
|
||||
// evaluate if data store field exists and return value(s) or null otherwise
|
||||
return (isset($this->data['replyTo'])) ? $this->data['replyTo'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of or one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setTo(IAddress ...$value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['to'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array<int,IAddress> collection of all recipient mail address objects
|
||||
*/
|
||||
public function getTo(): array {
|
||||
// evaluate if data store field exists and return value(s) or empty collection
|
||||
return (isset($this->data['to'])) ? $this->data['to'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of or one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setCc(IAddress ...$value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['cc'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array<int,IAddress> collection of all copied recipient mail address objects
|
||||
*/
|
||||
public function getCc(): array {
|
||||
// evaluate if data store field exists and return value(s) or empty collection
|
||||
return (isset($this->data['cc'])) ? $this->data['cc'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the blind copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAddress ...$value collection of or one or more mail address objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBcc(IAddress ...$value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['bcc'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the blind copy to recipient(s) of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param array<int,IAddress> collection of all blind copied recipient mail address objects
|
||||
*/
|
||||
public function getBcc(): array {
|
||||
// evaluate if data store field exists and return value(s) or empty collection
|
||||
return (isset($this->data['bcc'])) ? $this->data['bcc'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the subject of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value subject of mail message
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setSubject(string $value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['subject'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the subject of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null subject of message or null if one is not set
|
||||
*/
|
||||
public function getSubject(): string | null {
|
||||
// evaluate if data store field exists and return value(s) or null otherwise
|
||||
return (isset($this->data['subject'])) ? $this->data['subject'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the plain text or html body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value text or html body of message
|
||||
* @param bool $html html flag - true for html
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBody(string $value, bool $html = false): self {
|
||||
// evaluate html flag and create or update appropriate field in data store with value
|
||||
if ($html) {
|
||||
$this->data['bodyHtml'] = $value;
|
||||
} else {
|
||||
$this->data['bodyPlain'] = $value;
|
||||
}
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets either the html or plain text body of this message
|
||||
*
|
||||
* html body will be returned over plain text if html body exists
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null html/plain body of this message or null if one is not set
|
||||
*/
|
||||
public function getBody(): string | null {
|
||||
// evaluate if data store field(s) exists and return value
|
||||
if (isset($this->data['bodyHtml'])) {
|
||||
return $this->data['bodyHtml'];
|
||||
} elseif (isset($this->data['bodyPlain'])) {
|
||||
return $this->data['bodyPlain'];
|
||||
}
|
||||
// return null if data fields did not exist in data store
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the html body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value html body of message
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBodyHtml(string $value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['bodyHtml'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the html body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null html body of this message or null if one is not set
|
||||
*/
|
||||
public function getBodyHtml(): string | null {
|
||||
// evaluate if data store field exists and return value(s) or null otherwise
|
||||
return (isset($this->data['bodyHtml'])) ? $this->data['bodyHtml'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the plain text body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string $value plain text body of message
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setBodyPlain(string $value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['bodyPlain'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the plain text body of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param string|null plain text body of this message or null if one is not set
|
||||
*/
|
||||
public function getBodyPlain(): string | null {
|
||||
// evaluate if data store field exists and return value(s) or null otherwise
|
||||
return (isset($this->data['bodyPlain'])) ? $this->data['bodyPlain'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the attachments of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @param IAttachment ...$value collection of or one or more mail attachment objects
|
||||
*
|
||||
* @return self return this object for command chaining
|
||||
*/
|
||||
public function setAttachments(IAttachment ...$value): self {
|
||||
// create or update field in data store with value
|
||||
$this->data['attachments'] = $value;
|
||||
// return this object for command chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the attachments of this message
|
||||
*
|
||||
* @since 30.0.0
|
||||
*
|
||||
* @return array<int,IAttachment> collection of all mail attachment objects
|
||||
*/
|
||||
public function getAttachments(): array {
|
||||
// evaluate if data store field exists and return value(s) or null otherwise
|
||||
return (isset($this->data['attachments'])) ? $this->data['attachments'] : [];
|
||||
}
|
||||
|
||||
}
|
||||
46
tests/lib/Mail/Provider/AddressTest.php
Normal file
46
tests/lib/Mail/Provider/AddressTest.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace Test\Mail\Provider;
|
||||
|
||||
use OCP\Mail\Provider\Address;
|
||||
use Test\TestCase;
|
||||
|
||||
class AddressTest extends TestCase {
|
||||
|
||||
/** @var Address&MockObject */
|
||||
private Address $address;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->address = new Address('user1@testing.com', 'User One');
|
||||
|
||||
}
|
||||
|
||||
public function testAddress(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals('user1@testing.com', $this->address->getAddress());
|
||||
// test set by setter
|
||||
$this->address->setAddress('user2@testing.com');
|
||||
$this->assertEquals('user2@testing.com', $this->address->getAddress());
|
||||
|
||||
}
|
||||
|
||||
public function testLabel(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals('User One', $this->address->getLabel());
|
||||
// test set by setter
|
||||
$this->address->setLabel('User Two');
|
||||
$this->assertEquals('User Two', $this->address->getLabel());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
71
tests/lib/Mail/Provider/AttachmentTest.php
Normal file
71
tests/lib/Mail/Provider/AttachmentTest.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace Test\Mail\Provider;
|
||||
|
||||
use OCP\Mail\Provider\Attachment;
|
||||
use Test\TestCase;
|
||||
|
||||
class AttachmentTest extends TestCase {
|
||||
|
||||
/** @var Attachment&MockObject */
|
||||
private Attachment $attachment;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->attachment = new Attachment(
|
||||
'This is the contents of a file',
|
||||
'example1.txt',
|
||||
'text/plain',
|
||||
false
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function testName(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals('example1.txt', $this->attachment->getName());
|
||||
// test set by setter
|
||||
$this->attachment->setName('example2.txt');
|
||||
$this->assertEquals('example2.txt', $this->attachment->getName());
|
||||
|
||||
}
|
||||
|
||||
public function testType(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals('text/plain', $this->attachment->getType());
|
||||
// test set by setter
|
||||
$this->attachment->setType('text/html');
|
||||
$this->assertEquals('text/html', $this->attachment->getType());
|
||||
|
||||
}
|
||||
|
||||
public function testContents(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals('This is the contents of a file', $this->attachment->getContents());
|
||||
// test set by setter
|
||||
$this->attachment->setContents('This is the modified contents of a file');
|
||||
$this->assertEquals('This is the modified contents of a file', $this->attachment->getContents());
|
||||
|
||||
}
|
||||
|
||||
public function testEmbedded(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals(false, $this->attachment->getEmbedded());
|
||||
// test set by setter
|
||||
$this->attachment->setEmbedded(true);
|
||||
$this->assertEquals(true, $this->attachment->getEmbedded());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
189
tests/lib/Mail/Provider/ManagerTest.php
Normal file
189
tests/lib/Mail/Provider/ManagerTest.php
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace Test\Mail\Provider;
|
||||
|
||||
use OC\AppFramework\Bootstrap\Coordinator;
|
||||
use OC\AppFramework\Bootstrap\RegistrationContext;
|
||||
use OC\AppFramework\Bootstrap\ServiceRegistration;
|
||||
use OC\Mail\Provider\Manager;
|
||||
use OCP\Mail\Provider\Address;
|
||||
use OCP\Mail\Provider\IProvider;
|
||||
use OCP\Mail\Provider\IService;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
class ManagerTest extends TestCase {
|
||||
|
||||
/** @var Coordinator&MockObject */
|
||||
private Coordinator $coordinator;
|
||||
/** @var ContainerInterface&MockObject */
|
||||
private ContainerInterface $container;
|
||||
/** @var LoggerInterface&MockObject */
|
||||
private LoggerInterface $logger;
|
||||
/** @var IProvider&MockObject */
|
||||
private IProvider $provider;
|
||||
/** @var IService&MockObject */
|
||||
private IService $service;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
|
||||
// construct service registration
|
||||
$registration = $this->createMock(ServiceRegistration::class);
|
||||
$registration
|
||||
->method('getService')
|
||||
->willReturn('Mock\Provider\MailProvider');
|
||||
// construct registration context
|
||||
$context = $this->createMock(RegistrationContext::class);
|
||||
$context
|
||||
->method('getMailProviders')
|
||||
->willReturn([$registration]);
|
||||
// construct coordinator
|
||||
$this->coordinator = $this->createMock(Coordinator::class);
|
||||
$this->coordinator
|
||||
->method('getRegistrationContext')
|
||||
->willReturn($context);
|
||||
|
||||
// construct mail service
|
||||
$this->service = $this->createMock(IService::class);
|
||||
$this->service
|
||||
->method('id')
|
||||
->willReturn('100');
|
||||
$this->service
|
||||
->method('getLabel')
|
||||
->willReturn('Mock Mail Service');
|
||||
$this->service
|
||||
->method('getPrimaryAddress')
|
||||
->willReturn((new Address('user1@testing.com', 'User One')));
|
||||
// construct mail provider
|
||||
$this->provider = $this->createMock(IProvider::class);
|
||||
$this->provider
|
||||
->method('id')
|
||||
->willReturn('mock-provider');
|
||||
$this->provider
|
||||
->method('label')
|
||||
->willReturn('Mock Provider');
|
||||
$this->provider
|
||||
->method('listServices')
|
||||
->willReturnMap([
|
||||
['user0', []],
|
||||
['user1', [$this->service->id() => $this->service]]
|
||||
]);
|
||||
$this->provider
|
||||
->method('findServiceById')
|
||||
->willReturnMap([
|
||||
['user0', '100', null],
|
||||
['user1', '100', $this->service]
|
||||
]);
|
||||
$this->provider
|
||||
->method('findServiceByAddress')
|
||||
->willReturnMap([
|
||||
['user0', 'user0@testing.com', null],
|
||||
['user1', 'user1@testing.com', $this->service]
|
||||
]);
|
||||
// construct container interface
|
||||
$this->container = $this->createMock(ContainerInterface::class);
|
||||
$this->container
|
||||
->method('get')
|
||||
->willReturnMap([
|
||||
['Mock\Provider\MailProvider', $this->provider]
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function testHas(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with providers found
|
||||
$this->assertTrue($manager->has());
|
||||
|
||||
}
|
||||
|
||||
public function testCount(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with providers found
|
||||
$this->assertGreaterThan(0, $manager->count());
|
||||
|
||||
}
|
||||
|
||||
public function testTypes(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with providers found
|
||||
$this->assertEquals(['mock-provider' => 'Mock Provider'], $manager->types());
|
||||
|
||||
}
|
||||
|
||||
public function testProviders(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with providers found
|
||||
$this->assertEquals([$this->provider->id() => $this->provider], $manager->providers());
|
||||
|
||||
}
|
||||
|
||||
public function testFindProviderById(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with providers found
|
||||
$this->assertEquals($this->provider, $manager->findProviderById($this->provider->id()));
|
||||
|
||||
}
|
||||
|
||||
public function testServices(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with no services found
|
||||
$this->assertEquals([], $manager->services('user0'));
|
||||
// test result with services found
|
||||
$this->assertEquals([$this->provider->id() => [$this->service->id() => $this->service]], $manager->services('user1'));
|
||||
|
||||
}
|
||||
|
||||
public function testFindServiceById(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with no services found and not provider specified
|
||||
$this->assertEquals(null, $manager->findServiceById('user0', '100'));
|
||||
// test result with no services found and provider specified
|
||||
$this->assertEquals(null, $manager->findServiceById('user0', '100', $this->provider->id()));
|
||||
// test result with services found and not provider specified
|
||||
$this->assertEquals($this->service, $manager->findServiceById('user1', '100'));
|
||||
// test result with services found and provider specified
|
||||
$this->assertEquals($this->service, $manager->findServiceById('user1', '100', $this->provider->id()));
|
||||
|
||||
}
|
||||
|
||||
public function testFindServiceByAddress(): void {
|
||||
|
||||
// construct mail manager
|
||||
$manager = new Manager($this->coordinator, $this->container, $this->logger);
|
||||
// test result with no services found and not provider specified
|
||||
$this->assertEquals(null, $manager->findServiceByAddress('user0', 'user0@testing.com'));
|
||||
// test result with no services found and provider specified
|
||||
$this->assertEquals(null, $manager->findServiceByAddress('user0', 'user0@testing.com', $this->provider->id()));
|
||||
// test result with services found and not provider specified
|
||||
$this->assertEquals($this->service, $manager->findServiceByAddress('user1', 'user1@testing.com'));
|
||||
// test result with services found and provider specified
|
||||
$this->assertEquals($this->service, $manager->findServiceByAddress('user1', 'user1@testing.com', $this->provider->id()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
163
tests/lib/Mail/Provider/MessageTest.php
Normal file
163
tests/lib/Mail/Provider/MessageTest.php
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace Test\Mail\Provider;
|
||||
|
||||
use OCP\Mail\Provider\Address;
|
||||
use OCP\Mail\Provider\Attachment;
|
||||
use OCP\Mail\Provider\Message;
|
||||
use Test\TestCase;
|
||||
|
||||
class MessageTest extends TestCase {
|
||||
|
||||
/** @var Message&MockObject */
|
||||
private Message $message;
|
||||
/** @var Address&MockObject */
|
||||
private Address $address1;
|
||||
/** @var Address&MockObject */
|
||||
private Address $address2;
|
||||
/** @var Attachment&MockObject */
|
||||
private Attachment $attachment1;
|
||||
/** @var Attachment&MockObject */
|
||||
private Attachment $attachment2;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->message = new Message(
|
||||
['id' => 'cd02ea42-feac-4863-b9d8-484d16a587ea']
|
||||
);
|
||||
$this->address1 = new Address(
|
||||
'user1@testing.com',
|
||||
'User One'
|
||||
);
|
||||
$this->address2 = new Address(
|
||||
'user2@testing.com',
|
||||
'User Two'
|
||||
);
|
||||
$this->attachment1 = new Attachment(
|
||||
'This is the contents of the first attachment',
|
||||
'example1.txt',
|
||||
'text/plain',
|
||||
false
|
||||
);
|
||||
$this->attachment2 = new Attachment(
|
||||
'This is the contents of the second attachment',
|
||||
'example1.txt',
|
||||
'text/plain',
|
||||
false
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function testId(): void {
|
||||
|
||||
// test set by constructor
|
||||
$this->assertEquals('cd02ea42-feac-4863-b9d8-484d16a587ea', $this->message->id());
|
||||
|
||||
}
|
||||
|
||||
public function testFrom(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertNull($this->message->getFrom());
|
||||
// test set by setter
|
||||
$this->message->setFrom($this->address1);
|
||||
$this->assertEquals($this->address1, $this->message->getFrom());
|
||||
|
||||
}
|
||||
|
||||
public function testReplyTo(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertNull($this->message->getReplyTo());
|
||||
// test set by setter
|
||||
$this->message->setReplyTo($this->address1);
|
||||
$this->assertEquals($this->address1, $this->message->getReplyTo());
|
||||
|
||||
}
|
||||
|
||||
public function testTo(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertEquals([], $this->message->getTo());
|
||||
// test set by setter single
|
||||
$this->message->setTo($this->address1);
|
||||
$this->assertEquals([$this->address1], $this->message->getTo());
|
||||
// test set by setter multiple
|
||||
$this->message->setTo($this->address1, $this->address2);
|
||||
$this->assertEquals([$this->address1, $this->address2], $this->message->getTo());
|
||||
|
||||
}
|
||||
|
||||
public function testCc(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertEquals([], $this->message->getCc());
|
||||
// test set by setter single
|
||||
$this->message->setCc($this->address1);
|
||||
$this->assertEquals([$this->address1], $this->message->getCc());
|
||||
// test set by setter multiple
|
||||
$this->message->setCc($this->address1, $this->address2);
|
||||
$this->assertEquals([$this->address1, $this->address2], $this->message->getCc());
|
||||
|
||||
}
|
||||
|
||||
public function testBcc(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertEquals([], $this->message->getBcc());
|
||||
// test set by setter single
|
||||
$this->message->setBcc($this->address1);
|
||||
$this->assertEquals([$this->address1], $this->message->getBcc());
|
||||
// test set by setter multiple
|
||||
$this->message->setBcc($this->address1, $this->address2);
|
||||
$this->assertEquals([$this->address1, $this->address2], $this->message->getBcc());
|
||||
|
||||
}
|
||||
|
||||
public function testSubject(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertNull($this->message->getSubject());
|
||||
// test set by setter
|
||||
$this->message->setSubject('Testing Mail Subject');
|
||||
$this->assertEquals('Testing Mail Subject', $this->message->getSubject());
|
||||
|
||||
}
|
||||
|
||||
public function testBody(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertNull($this->message->getBody());
|
||||
// test set by setter - text body
|
||||
$this->message->setBody('Testing Text Body', false);
|
||||
$this->assertEquals('Testing Text Body', $this->message->getBody());
|
||||
$this->message->setBodyPlain('Testing Text Body Again', false);
|
||||
$this->assertEquals('Testing Text Body Again', $this->message->getBodyPlain());
|
||||
// test set by setter - html body
|
||||
$this->message->setBody('Testing HTML Body', true);
|
||||
$this->assertEquals('Testing HTML Body', $this->message->getBody());
|
||||
$this->message->setBodyHtml('Testing HTML Body Again', false);
|
||||
$this->assertEquals('Testing HTML Body Again', $this->message->getBodyHtml());
|
||||
|
||||
}
|
||||
|
||||
public function testAttachments(): void {
|
||||
|
||||
// test not set
|
||||
$this->assertEquals([], $this->message->getAttachments());
|
||||
// test set by setter single
|
||||
$this->message->setAttachments($this->attachment1);
|
||||
$this->assertEquals([$this->attachment1], $this->message->getAttachments());
|
||||
// test set by setter multiple
|
||||
$this->message->setAttachments($this->attachment1, $this->attachment2);
|
||||
$this->assertEquals([$this->attachment1, $this->attachment2], $this->message->getAttachments());
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue