]> source.dussan.org Git - nextcloud-server.git/commitdiff
feat: mail provider settings backport/48134/stable30 49254/head
authorSebastianKrupinski <krupinskis05@gmail.com>
Tue, 17 Sep 2024 11:45:44 +0000 (07:45 -0400)
committerSebastianKrupinski <krupinskis05@gmail.com>
Fri, 15 Nov 2024 01:26:22 +0000 (20:26 -0500)
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
apps/dav/lib/CalDAV/Schedule/IMipPlugin.php
apps/dav/lib/Server.php
apps/dav/tests/unit/CalDAV/Schedule/IMipPluginTest.php
apps/settings/composer/composer/autoload_classmap.php
apps/settings/composer/composer/autoload_static.php
apps/settings/lib/AppInfo/Application.php
apps/settings/lib/Listener/MailProviderListener.php [new file with mode: 0644]
apps/settings/lib/Settings/Admin/MailProvider.php [new file with mode: 0644]

index 1cfe8f47cb5b7eb1387ae893cb1efa3922d4b97e..8ed3cf4d56f71d0f7e5a5c8853466d2801387425 100644 (file)
@@ -12,7 +12,7 @@ use OCA\DAV\CalDAV\CalendarObject;
 use OCA\DAV\CalDAV\EventComparisonService;
 use OCP\AppFramework\Utility\ITimeFactory;
 use OCP\Defaults;
-use OCP\IConfig;
+use OCP\IAppConfig;
 use OCP\IUserSession;
 use OCP\Mail\IMailer;
 use OCP\Mail\Provider\IManager as IMailManager;
@@ -44,7 +44,7 @@ use Sabre\VObject\Reader;
  */
 class IMipPlugin extends SabreIMipPlugin {
        private IUserSession $userSession;
-       private IConfig $config;
+       private IAppConfig $config;
        private IMailer $mailer;
        private LoggerInterface $logger;
        private ITimeFactory $timeFactory;
@@ -59,7 +59,8 @@ class IMipPlugin extends SabreIMipPlugin {
        private EventComparisonService $eventComparisonService;
        private IMailManager $mailManager;
 
-       public function __construct(IConfig $config,
+       public function __construct(
+               IAppConfig $config,
                IMailer $mailer,
                LoggerInterface $logger,
                ITimeFactory $timeFactory,
@@ -254,7 +255,7 @@ class IMipPlugin extends SabreIMipPlugin {
                        */
 
                        $recipientDomain = substr(strrchr($recipient, '@'), 1);
-                       $invitationLinkRecipients = explode(',', preg_replace('/\s+/', '', strtolower($this->config->getAppValue('dav', 'invitation_link_recipients', 'yes'))));
+                       $invitationLinkRecipients = explode(',', preg_replace('/\s+/', '', strtolower($this->config->getValueString('dav', 'invitation_link_recipients', 'yes'))));
 
                        if (strcmp('yes', $invitationLinkRecipients[0]) === 0
                                || in_array(strtolower($recipient), $invitationLinkRecipients)
@@ -273,12 +274,13 @@ class IMipPlugin extends SabreIMipPlugin {
                $mailService = null;
 
                try {
-                       // 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);
+                       if ($this->config->getValueBool('core', 'mail_providers_enabled', true)) {
+                               // retrieve user object
+                               $user = $this->userSession->getUser();
+                               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) {
index 55c8a5afec1f2944d3d81f33f0d3d7cb5294d1c1..f4b8dcaf3a10be346f62682c5bf73f875b79c92c 100644 (file)
@@ -55,6 +55,7 @@ use OCP\Diagnostics\IEventLogger;
 use OCP\EventDispatcher\IEventDispatcher;
 use OCP\Files\IFilenameValidator;
 use OCP\FilesMetadata\IFilesMetadataManager;
+use OCP\IAppConfig;
 use OCP\ICacheFactory;
 use OCP\IConfig;
 use OCP\IPreview;
@@ -289,7 +290,7 @@ class Server {
                                ));
                                if (\OC::$server->getConfig()->getAppValue('dav', 'sendInvitations', 'yes') === 'yes') {
                                        $this->server->addPlugin(new IMipPlugin(
-                                               \OC::$server->get(\OCP\IConfig::class),
+                                               \OC::$server->get(IAppConfig::class),
                                                \OC::$server->get(\OCP\Mail\IMailer::class),
                                                \OC::$server->get(LoggerInterface::class),
                                                \OC::$server->get(\OCP\AppFramework\Utility\ITimeFactory::class),
index c8dfe257bf2bbfd8ba544f8c5e75e3633986651d..b459b9da7c85babe100cd149676a84e9d912fa6b 100644 (file)
@@ -11,7 +11,7 @@ use OCA\DAV\CalDAV\Schedule\IMipPlugin;
 use OCA\DAV\CalDAV\Schedule\IMipService;
 use OCP\AppFramework\Utility\ITimeFactory;
 use OCP\Defaults;
-use OCP\IConfig;
+use OCP\IAppConfig;
 use OCP\IUser;
 use OCP\IUserSession;
 use OCP\Mail\IAttachment;
@@ -52,7 +52,7 @@ class IMipPluginTest extends TestCase {
        /** @var ITimeFactory|MockObject */
        private $timeFactory;
 
-       /** @var IConfig|MockObject */
+       /** @var IAppConfig|MockObject */
        private $config;
 
        /** @var IUserSession|MockObject */
@@ -105,7 +105,7 @@ class IMipPluginTest extends TestCase {
                $this->timeFactory = $this->createMock(ITimeFactory::class);
                $this->timeFactory->method('getTime')->willReturn(1496912528); // 2017-01-01
 
-               $this->config = $this->createMock(IConfig::class);
+               $this->config = $this->createMock(IAppConfig::class);
 
                $this->user = $this->createMock(IUser::class);
 
@@ -243,7 +243,7 @@ class IMipPluginTest extends TestCase {
                        ->method('getAttendeeRsvpOrReqForParticipant')
                        ->willReturn(true);
                $this->config->expects(self::once())
-                       ->method('getAppValue')
+                       ->method('getValueString')
                        ->with('dav', 'invitation_link_recipients', 'yes')
                        ->willReturn('yes');
                $this->service->expects(self::once())
@@ -341,7 +341,7 @@ class IMipPluginTest extends TestCase {
                $this->service->expects(self::never())
                        ->method('getAttendeeRsvpOrReqForParticipant');
                $this->config->expects(self::never())
-                       ->method('getAppValue');
+                       ->method('getValueString');
                $this->service->expects(self::never())
                        ->method('createInvitationToken');
                $this->service->expects(self::never())
@@ -447,7 +447,7 @@ class IMipPluginTest extends TestCase {
                        ->method('getAttendeeRsvpOrReqForParticipant')
                        ->willReturn(true);
                $this->config->expects(self::once())
-                       ->method('getAppValue')
+                       ->method('getValueString')
                        ->with('dav', 'invitation_link_recipients', 'yes')
                        ->willReturn('yes');
                $this->service->expects(self::once())
@@ -578,7 +578,7 @@ class IMipPluginTest extends TestCase {
                        ->method('getAttendeeRsvpOrReqForParticipant')
                        ->willReturn(true);
                $this->config->expects(self::once())
-                       ->method('getAppValue')
+                       ->method('getValueString')
                        ->with('dav', 'invitation_link_recipients', 'yes')
                        ->willReturn('yes');
                $this->service->expects(self::once())
@@ -633,7 +633,7 @@ class IMipPluginTest extends TestCase {
                ];
                // construct system config mock returns
                $this->config->expects(self::once())
-                       ->method('getAppValue')
+                       ->method('getValueString')
                        ->with('dav', 'invitation_link_recipients', 'yes')
                        ->willReturn('yes');
                // construct user mock returns
@@ -708,6 +708,113 @@ class IMipPluginTest extends TestCase {
                $this->assertEquals('1.1', $message->getScheduleStatus());
        }
 
+       public function testMailProviderDisabled(): void {
+               $message = new Message();
+               $message->method = 'REQUEST';
+               $newVCalendar = new VCalendar();
+               $newVevent = new VEvent($newVCalendar, 'one', array_merge([
+                       'UID' => 'uid-1234',
+                       'SEQUENCE' => 1,
+                       'SUMMARY' => 'Fellowship meeting without (!) Boromir',
+                       'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+               ], []));
+               $newVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+               $newVevent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE',  'CN' => 'Frodo']);
+               $message->message = $newVCalendar;
+               $message->sender = 'mailto:gandalf@wiz.ard';
+               $message->senderName = 'Mr. Wizard';
+               $message->recipient = 'mailto:' . 'frodo@hobb.it';
+               // save the old copy in the plugin
+               $oldVCalendar = new VCalendar();
+               $oldVEvent = new VEvent($oldVCalendar, 'one', [
+                       'UID' => 'uid-1234',
+                       'SEQUENCE' => 0,
+                       'SUMMARY' => 'Fellowship meeting',
+                       'DTSTART' => new \DateTime('2016-01-01 00:00:00')
+               ]);
+               $oldVEvent->add('ORGANIZER', 'mailto:gandalf@wiz.ard');
+               $oldVEvent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']);
+               $oldVEvent->add('ATTENDEE', 'mailto:' . 'boromir@tra.it.or', ['RSVP' => 'TRUE']);
+               $oldVCalendar->add($oldVEvent);
+               $data = ['invitee_name' => 'Mr. Wizard',
+                       'meeting_title' => 'Fellowship meeting without (!) Boromir',
+                       'attendee_name' => 'frodo@hobb.it'
+               ];
+               $attendees = $newVevent->select('ATTENDEE');
+               $atnd = '';
+               foreach ($attendees as $attendee) {
+                       if (strcasecmp($attendee->getValue(), $message->recipient) === 0) {
+                               $atnd = $attendee;
+                       }
+               }
+               $this->plugin->setVCalendar($oldVCalendar);
+               $this->service->expects(self::once())
+                       ->method('getLastOccurrence')
+                       ->willReturn(1496912700);
+               $this->mailer->expects(self::once())
+                       ->method('validateMailAddress')
+                       ->with('frodo@hobb.it')
+                       ->willReturn(true);
+               $this->eventComparisonService->expects(self::once())
+                       ->method('findModified')
+                       ->willReturn(['new' => [$newVevent], 'old' => [$oldVEvent]]);
+               $this->service->expects(self::once())
+                       ->method('getCurrentAttendee')
+                       ->with($message)
+                       ->willReturn($atnd);
+               $this->service->expects(self::once())
+                       ->method('isRoomOrResource')
+                       ->with($atnd)
+                       ->willReturn(false);
+               $this->service->expects(self::once())
+                       ->method('buildBodyData')
+                       ->with($newVevent, $oldVEvent)
+                       ->willReturn($data);
+               $this->user->expects(self::any())
+                       ->method('getUID')
+                       ->willReturn('user1');
+               $this->user->expects(self::any())
+                       ->method('getDisplayName')
+                       ->willReturn('Mr. Wizard');
+               $this->userSession->expects(self::any())
+                       ->method('getUser')
+                       ->willReturn($this->user);
+               $this->service->expects(self::once())
+                       ->method('getFrom');
+               $this->service->expects(self::once())
+                       ->method('addSubjectAndHeading')
+                       ->with($this->emailTemplate, 'request', 'Mr. Wizard', 'Fellowship meeting without (!) Boromir', true);
+               $this->service->expects(self::once())
+                       ->method('addBulletList')
+                       ->with($this->emailTemplate, $newVevent, $data);
+               $this->service->expects(self::once())
+                       ->method('getAttendeeRsvpOrReqForParticipant')
+                       ->willReturn(true);
+               $this->config->expects(self::once())
+                       ->method('getValueString')
+                       ->with('dav', 'invitation_link_recipients', 'yes')
+                       ->willReturn('yes');
+               $this->config->expects(self::once())
+                       ->method('getValueBool')
+                       ->with('core', 'mail_providers_enabled', true)
+                       ->willReturn(false);
+               $this->service->expects(self::once())
+                       ->method('createInvitationToken')
+                       ->with($message, $newVevent, 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->mailer->expects(self::once())
+                       ->method('send')
+                       ->willReturn([]);
+               $this->plugin->schedule($message);
+               $this->assertEquals('1.1', $message->getScheduleStatus());
+       }
+
        public function testNoOldEvent(): void {
                $message = new Message();
                $message->method = 'REQUEST';
@@ -779,7 +886,7 @@ class IMipPluginTest extends TestCase {
                        ->method('getAttendeeRsvpOrReqForParticipant')
                        ->willReturn(true);
                $this->config->expects(self::once())
-                       ->method('getAppValue')
+                       ->method('getValueString')
                        ->with('dav', 'invitation_link_recipients', 'yes')
                        ->willReturn('yes');
                $this->service->expects(self::once())
@@ -872,7 +979,7 @@ class IMipPluginTest extends TestCase {
                        ->method('getAttendeeRsvpOrReqForParticipant')
                        ->willReturn(true);
                $this->config->expects(self::once())
-                       ->method('getAppValue')
+                       ->method('getValueString')
                        ->with('dav', 'invitation_link_recipients', 'yes')
                        ->willReturn('no');
                $this->service->expects(self::never())
index 41f70c3a8e67ff4fb045470e56ea0e09de70b38a..58020673a1c4951ef4b8671210aec55af2f2b54a 100644 (file)
@@ -40,6 +40,7 @@ return array(
     'OCA\\Settings\\Hooks' => $baseDir . '/../lib/Hooks.php',
     'OCA\\Settings\\Listener\\AppPasswordCreatedActivityListener' => $baseDir . '/../lib/Listener/AppPasswordCreatedActivityListener.php',
     'OCA\\Settings\\Listener\\GroupRemovedListener' => $baseDir . '/../lib/Listener/GroupRemovedListener.php',
+    'OCA\\Settings\\Listener\\MailProviderListener' => $baseDir . '/../lib/Listener/MailProviderListener.php',
     'OCA\\Settings\\Listener\\UserAddedToGroupActivityListener' => $baseDir . '/../lib/Listener/UserAddedToGroupActivityListener.php',
     'OCA\\Settings\\Listener\\UserRemovedFromGroupActivityListener' => $baseDir . '/../lib/Listener/UserRemovedFromGroupActivityListener.php',
     'OCA\\Settings\\Mailer\\NewUserMailHelper' => $baseDir . '/../lib/Mailer/NewUserMailHelper.php',
@@ -67,6 +68,7 @@ return array(
     'OCA\\Settings\\Settings\\Admin\\ArtificialIntelligence' => $baseDir . '/../lib/Settings/Admin/ArtificialIntelligence.php',
     'OCA\\Settings\\Settings\\Admin\\Delegation' => $baseDir . '/../lib/Settings/Admin/Delegation.php',
     'OCA\\Settings\\Settings\\Admin\\Mail' => $baseDir . '/../lib/Settings/Admin/Mail.php',
+    'OCA\\Settings\\Settings\\Admin\\MailProvider' => $baseDir . '/../lib/Settings/Admin/MailProvider.php',
     'OCA\\Settings\\Settings\\Admin\\Overview' => $baseDir . '/../lib/Settings/Admin/Overview.php',
     'OCA\\Settings\\Settings\\Admin\\Security' => $baseDir . '/../lib/Settings/Admin/Security.php',
     'OCA\\Settings\\Settings\\Admin\\Server' => $baseDir . '/../lib/Settings/Admin/Server.php',
index 4fa905b55bb7cc527eb48c310ebd238799bb41d9..e500cd19d612e6fc3eb4425d9dd005f8074667e9 100644 (file)
@@ -55,6 +55,7 @@ class ComposerStaticInitSettings
         'OCA\\Settings\\Hooks' => __DIR__ . '/..' . '/../lib/Hooks.php',
         'OCA\\Settings\\Listener\\AppPasswordCreatedActivityListener' => __DIR__ . '/..' . '/../lib/Listener/AppPasswordCreatedActivityListener.php',
         'OCA\\Settings\\Listener\\GroupRemovedListener' => __DIR__ . '/..' . '/../lib/Listener/GroupRemovedListener.php',
+        'OCA\\Settings\\Listener\\MailProviderListener' => __DIR__ . '/..' . '/../lib/Listener/MailProviderListener.php',
         'OCA\\Settings\\Listener\\UserAddedToGroupActivityListener' => __DIR__ . '/..' . '/../lib/Listener/UserAddedToGroupActivityListener.php',
         'OCA\\Settings\\Listener\\UserRemovedFromGroupActivityListener' => __DIR__ . '/..' . '/../lib/Listener/UserRemovedFromGroupActivityListener.php',
         'OCA\\Settings\\Mailer\\NewUserMailHelper' => __DIR__ . '/..' . '/../lib/Mailer/NewUserMailHelper.php',
@@ -82,6 +83,7 @@ class ComposerStaticInitSettings
         'OCA\\Settings\\Settings\\Admin\\ArtificialIntelligence' => __DIR__ . '/..' . '/../lib/Settings/Admin/ArtificialIntelligence.php',
         'OCA\\Settings\\Settings\\Admin\\Delegation' => __DIR__ . '/..' . '/../lib/Settings/Admin/Delegation.php',
         'OCA\\Settings\\Settings\\Admin\\Mail' => __DIR__ . '/..' . '/../lib/Settings/Admin/Mail.php',
+        'OCA\\Settings\\Settings\\Admin\\MailProvider' => __DIR__ . '/..' . '/../lib/Settings/Admin/MailProvider.php',
         'OCA\\Settings\\Settings\\Admin\\Overview' => __DIR__ . '/..' . '/../lib/Settings/Admin/Overview.php',
         'OCA\\Settings\\Settings\\Admin\\Security' => __DIR__ . '/..' . '/../lib/Settings/Admin/Security.php',
         'OCA\\Settings\\Settings\\Admin\\Server' => __DIR__ . '/..' . '/../lib/Settings/Admin/Server.php',
index 80420cb3335cf7856cd1cf1d57b15f6790a2ab90..0d71d9c67eff6b23827bb2f16ac2d0b27272143f 100644 (file)
@@ -15,6 +15,7 @@ use OC\Server;
 use OCA\Settings\Hooks;
 use OCA\Settings\Listener\AppPasswordCreatedActivityListener;
 use OCA\Settings\Listener\GroupRemovedListener;
+use OCA\Settings\Listener\MailProviderListener;
 use OCA\Settings\Listener\UserAddedToGroupActivityListener;
 use OCA\Settings\Listener\UserRemovedFromGroupActivityListener;
 use OCA\Settings\Mailer\NewUserMailHelper;
@@ -22,6 +23,7 @@ use OCA\Settings\Middleware\SubadminMiddleware;
 use OCA\Settings\Search\AppSearch;
 use OCA\Settings\Search\SectionSearch;
 use OCA\Settings\Search\UserSearch;
+use OCA\Settings\Settings\Admin\MailProvider;
 use OCA\Settings\SetupChecks\AllowedAdminRanges;
 use OCA\Settings\SetupChecks\AppDirsWithDifferentOwner;
 use OCA\Settings\SetupChecks\BruteForceThrottler;
@@ -83,6 +85,8 @@ use OCP\Group\Events\GroupDeletedEvent;
 use OCP\Group\Events\UserAddedEvent;
 use OCP\Group\Events\UserRemovedEvent;
 use OCP\IServerContainer;
+use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
+use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
 use OCP\Settings\IManager;
 use OCP\Util;
 
@@ -110,10 +114,17 @@ class Application extends App implements IBootstrap {
                $context->registerEventListener(UserRemovedEvent::class, UserRemovedFromGroupActivityListener::class);
                $context->registerEventListener(GroupDeletedEvent::class, GroupRemovedListener::class);
 
+               // Register Mail Provider listeners
+               $context->registerEventListener(DeclarativeSettingsGetValueEvent::class, MailProviderListener::class);
+               $context->registerEventListener(DeclarativeSettingsSetValueEvent::class, MailProviderListener::class);
+
                // Register well-known handlers
                $context->registerWellKnownHandler(SecurityTxtHandler::class);
                $context->registerWellKnownHandler(ChangePasswordHandler::class);
 
+               // Register Settings Form(s)
+               $context->registerDeclarativeSettings(MailProvider::class);
+
                /**
                 * Core class wrappers
                 */
diff --git a/apps/settings/lib/Listener/MailProviderListener.php b/apps/settings/lib/Listener/MailProviderListener.php
new file mode 100644 (file)
index 0000000..974378c
--- /dev/null
@@ -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 OCA\Settings\Listener;
+
+use OCA\Settings\AppInfo\Application;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\IAppConfig;
+use OCP\Settings\Events\DeclarativeSettingsGetValueEvent;
+use OCP\Settings\Events\DeclarativeSettingsSetValueEvent;
+
+/** @template-implements IEventListener<DeclarativeSettingsGetValueEvent|DeclarativeSettingsSetValueEvent> */
+class MailProviderListener implements IEventListener {
+
+       public function __construct(
+               private IAppConfig $config,
+       ) {
+       }
+
+       public function handle(Event $event): void {
+
+               /** @var DeclarativeSettingsGetValueEvent|DeclarativeSettingsSetValueEvent $event */
+               if ($event->getApp() !== Application::APP_ID) {
+                       return;
+               }
+
+               if ($event instanceof DeclarativeSettingsGetValueEvent) {
+                       $this->handleGetValue($event);
+                       return;
+               }
+
+               if ($event instanceof DeclarativeSettingsSetValueEvent) {
+                       $this->handleSetValue($event);
+                       return;
+               }
+               
+       }
+
+       private function handleGetValue(DeclarativeSettingsGetValueEvent $event): void {
+               
+               if ($event->getFieldId() === 'mail_providers_enabled') {
+                       $event->setValue((int)$this->config->getValueBool('core', 'mail_providers_enabled', true));
+               }
+
+       }
+
+       private function handleSetValue(DeclarativeSettingsSetValueEvent $event): void {
+
+               if ($event->getFieldId() === 'mail_providers_enabled') {
+                       $this->config->setValueBool('core', 'mail_providers_enabled', (bool)$event->getValue());
+                       $event->stopPropagation();
+               }
+
+       }
+
+}
diff --git a/apps/settings/lib/Settings/Admin/MailProvider.php b/apps/settings/lib/Settings/Admin/MailProvider.php
new file mode 100644 (file)
index 0000000..edbb484
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Settings\Settings\Admin;
+
+use OCP\IL10N;
+use OCP\Settings\DeclarativeSettingsTypes;
+use OCP\Settings\IDeclarativeSettingsForm;
+
+class MailProvider implements IDeclarativeSettingsForm {
+
+       public function __construct(
+               private IL10N $l,
+       ) {
+       }
+
+       public function getSchema(): array {
+               return [
+                       'id' => 'mail-provider-support',
+                       'priority' => 10,
+                       'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN,
+                       'section_id' => 'server',
+                       'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL,
+                       'title' => $this->l->t('Mail Providers'),
+                       'description' => $this->l->t('Mail provider enables sending emails directly through the user\'s personal email account. At present, this functionality is limited to calendar invitations. It requires Nextcloud Mail 4.1 and an email account in Nextcloud Mail that matches the user\'s email address in Nextcloud.'),
+
+                       'fields' => [
+                               [
+                                       'id' => 'mail_providers_enabled',
+                                       'title' => $this->l->t('Send emails using'),
+                                       'type' => DeclarativeSettingsTypes::RADIO,
+                                       'default' => 1,
+                                       'options' => [
+                                               [
+                                                       'name' => $this->l->t('Users\'s email account'),
+                                                       'value' => 1
+                                               ],
+                                               [
+                                                       'name' => $this->l->t('System email account'),
+                                                       'value' => 0
+                                               ],
+                                       ],
+                               ],
+                       ],
+               ];
+       }
+
+}