diff --git a/dd-apps/docker/nextcloud/dd-patch b/dd-apps/docker/nextcloud/dd-patch
index 9b8b74c..0084ea6 100644
--- a/dd-apps/docker/nextcloud/dd-patch
+++ b/dd-apps/docker/nextcloud/dd-patch
@@ -1,3 +1,9 @@
# Generate .orig and .patch files with ./dd-ctl genpatches
# file license author source
nginx.conf AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/nextcloud/docker/522559eefdd56d2e49259c3b0f4a0e92882cdb87/.examples/docker-compose/with-nginx-proxy/postgres/fpm/web/nginx.conf
+#nc_mail/appinfo.xml AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/MaadixNet/mail/feature/occ-account-update-command/appinfo/info.xml
+#nc_mail/lib/Command/UpdateAccount.php AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/MaadixNet/mail/feature/occ-account-update-command/lib/Command/UpdateAccount.php
+#nc_mail/lib/Db/MailAccountMapper.php AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/MaadixNet/mail/feature/occ-account-update-command/lib/Db/MailAccountMapper.php
+nc_mail/appinfo/info.xml AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/nextcloud/mail/v1.12.8/appinfo/info.xml
+nc_mail/lib/Command/UpdateAccount.php AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/nextcloud/mail/v1.12.8/lib/Command/UpdateAccount.php
+nc_mail/lib/Db/MailAccountMapper.php AGPL-3.0-or-later https://github.com/nextcloud/ https://raw.githubusercontent.com/nextcloud/mail/v1.12.8/lib/Db/MailAccountMapper.php
diff --git a/dd-apps/docker/nextcloud/nc_mail/appinfo/info.xml b/dd-apps/docker/nextcloud/nc_mail/appinfo/info.xml
new file mode 100644
index 0000000..a7e8311
--- /dev/null
+++ b/dd-apps/docker/nextcloud/nc_mail/appinfo/info.xml
@@ -0,0 +1,75 @@
+
+
+ mail
+ Mail
+ ๐ A mail app for Nextcloud
+
+ 1.12.8
+ agpl
+ Greta Doรงi
+ Nextcloud Groupware Team
+ Mail
+
+ https://github.com/nextcloud/mail/blob/main/doc/user.md
+ https://github.com/nextcloud/mail/blob/main/doc/admin.md
+ https://github.com/nextcloud/mail/blob/main/doc/developer.md
+
+ social
+ office
+ https://github.com/nextcloud/mail#readme
+ https://github.com/nextcloud/mail/issues
+ https://github.com/nextcloud/mail.git
+ https://user-images.githubusercontent.com/1374172/79554966-278e1600-809f-11ea-82ea-7a0d72a2704f.png
+
+
+
+
+
+ OCA\Mail\BackgroundJob\CleanupJob
+ OCA\Mail\BackgroundJob\OutboxWorkerJob
+
+
+
+ OCA\Mail\Migration\AddMissingDefaultTags
+ OCA\Mail\Migration\AddMissingMessageIds
+ OCA\Mail\Migration\FixCollectedAddresses
+ OCA\Mail\Migration\FixBackgroundJobs
+ OCA\Mail\Migration\MakeItineraryExtractorExecutable
+ OCA\Mail\Migration\ProvisionAccounts
+ OCA\Mail\Migration\RepairMailTheads
+
+
+
+ OCA\Mail\Command\AddMissingTags
+ OCA\Mail\Command\CleanUp
+ OCA\Mail\Command\CreateAccount
+ OCA\Mail\Command\CreateTagMigrationJobEntry
+ OCA\Mail\Command\DeleteAccount
+ OCA\Mail\Command\DiagnoseAccount
+ OCA\Mail\Command\ExportAccount
+ OCA\Mail\Command\ExportAccountThreads
+ OCA\Mail\Command\SyncAccount
+ OCA\Mail\Command\TrainAccount
+ OCA\Mail\Command\Thread
+ OCA\Mail\Command\UpdateAccount
+
+
+ OCA\Mail\Settings\AdminSettings
+
+
+
+ Mail
+ mail.page.index
+ mail.svg
+ 3
+
+
+
diff --git a/dd-apps/docker/nextcloud/nc_mail/lib/Command/UpdateAccount.php b/dd-apps/docker/nextcloud/nc_mail/lib/Command/UpdateAccount.php
new file mode 100644
index 0000000..e6f6324
--- /dev/null
+++ b/dd-apps/docker/nextcloud/nc_mail/lib/Command/UpdateAccount.php
@@ -0,0 +1,154 @@
+
+ * @author Maadix
+ *
+ * Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\Mail\Command;
+
+use OCA\Mail\Db\MailAccountMapper;
+use OCP\Security\ICrypto;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class UpdateAccount extends Command {
+ public const ARGUMENT_USER_ID = 'user-id';
+ public const ARGUMENT_EMAIL = 'email';
+ public const ARGUMENT_IMAP_HOST = 'imap-host';
+ public const ARGUMENT_IMAP_PORT = 'imap-port';
+ public const ARGUMENT_IMAP_SSL_MODE = 'imap-ssl-mode';
+ public const ARGUMENT_IMAP_USER = 'imap-user';
+ public const ARGUMENT_IMAP_PASSWORD = 'imap-password';
+ public const ARGUMENT_SMTP_HOST = 'smtp-host';
+ public const ARGUMENT_SMTP_PORT = 'smtp-port';
+ public const ARGUMENT_SMTP_SSL_MODE = 'smtp-ssl-mode';
+ public const ARGUMENT_SMTP_USER = 'smtp-user';
+ public const ARGUMENT_SMTP_PASSWORD = 'smtp-password';
+
+ /** @var mapper */
+ private $mapper;
+
+ /** @var ICrypto */
+ private $crypto;
+
+ public function __construct(MailAccountMapper $mapper, ICrypto $crypto) {
+ parent::__construct();
+
+ $this->mapper = $mapper;
+ $this->crypto = $crypto;
+ }
+
+ /**
+ * @return void
+ */
+ protected function configure() {
+ $this->setName('mail:account:update');
+ $this->setDescription('Update a user\'s IMAP account');
+ $this->addArgument(self::ARGUMENT_USER_ID, InputArgument::REQUIRED);
+ $this->addArgument(self::ARGUMENT_EMAIL, InputArgument::REQUIRED);
+
+ $this->addOption(self::ARGUMENT_IMAP_HOST, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_IMAP_PORT, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_IMAP_SSL_MODE, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_IMAP_USER, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_IMAP_PASSWORD, '', InputOption::VALUE_OPTIONAL);
+
+ $this->addOption(self::ARGUMENT_SMTP_HOST, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_SMTP_PORT, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_SMTP_SSL_MODE, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_SMTP_USER, '', InputOption::VALUE_OPTIONAL);
+ $this->addOption(self::ARGUMENT_SMTP_PASSWORD, '', InputOption::VALUE_OPTIONAL);
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $userId = $input->getArgument(self::ARGUMENT_USER_ID);
+ $email = $input->getArgument(self::ARGUMENT_EMAIL);
+
+ $imapHost = $input->getOption(self::ARGUMENT_IMAP_HOST);
+ $imapPort = $input->getOption(self::ARGUMENT_IMAP_PORT);
+ $imapSslMode = $input->getOption(self::ARGUMENT_IMAP_SSL_MODE);
+ $imapUser = $input->getOption(self::ARGUMENT_IMAP_USER);
+ $imapPassword = $input->getOption(self::ARGUMENT_IMAP_PASSWORD);
+
+ $smtpHost = $input->getOption(self::ARGUMENT_SMTP_HOST);
+ $smtpPort = $input->getOption(self::ARGUMENT_SMTP_PORT);
+ $smtpSslMode = $input->getOption(self::ARGUMENT_SMTP_SSL_MODE);
+ $smtpUser = $input->getOption(self::ARGUMENT_SMTP_USER);
+ $smtpPassword = $input->getOption(self::ARGUMENT_SMTP_PASSWORD);
+
+ $mailAccount = $this->mapper->findByUserIdAndEmail($userId, $email);
+
+ if ($mailAccount) {
+ //INBOUND
+ if ($input->getOption(self::ARGUMENT_IMAP_HOST)) {
+ $mailAccount->setInboundHost($imapHost);
+ }
+
+ if ($input->getOption(self::ARGUMENT_IMAP_PORT)) {
+ $mailAccount->setInboundPort((int) $imapPort);
+ }
+
+ if ($input->getOption(self::ARGUMENT_IMAP_SSL_MODE)) {
+ $mailAccount->setInboundSslMode($imapSslMode);
+ }
+
+ if ($input->getOption(self::ARGUMENT_IMAP_PASSWORD)) {
+ $mailAccount->setInboundPassword($this->crypto->encrypt($imapPassword));
+ }
+
+ if ($input->getOption(self::ARGUMENT_SMTP_USER)) {
+ $mailAccount->setInboundUser($imapUser);
+ }
+
+ // OUTBOUND
+
+ if ($input->getOption(self::ARGUMENT_SMTP_HOST)) {
+ $mailAccount->setOutboundHost($smtpHost);
+ }
+
+ if ($input->getOption(self::ARGUMENT_SMTP_PORT)) {
+ $mailAccount->setOutboundPort((int) $smtpPort);
+ }
+
+ if ($input->getOption(self::ARGUMENT_SMTP_SSL_MODE)) {
+ $mailAccount->setOutboundSslMode($smtpSslMode);
+ }
+
+ if ($input->getOption(self::ARGUMENT_SMTP_PASSWORD)) {
+ $mailAccount->setOutboundPassword($this->crypto->encrypt($smtpPassword));
+ }
+
+ if ($input->getOption(self::ARGUMENT_SMTP_USER)) {
+ $mailAccount->setOutboundUser($smtpUser);
+ }
+
+ $this->mapper->save($mailAccount);
+
+ $output->writeln("Account $email for user $userId succesfully updated ");
+ return 1;
+ } else {
+ $output->writeln("No Email Account $email found for user $userId ");
+ }
+
+ return 0;
+ }
+}
diff --git a/dd-apps/docker/nextcloud/nc_mail/lib/Db/MailAccountMapper.php b/dd-apps/docker/nextcloud/nc_mail/lib/Db/MailAccountMapper.php
new file mode 100644
index 0000000..6c5113b
--- /dev/null
+++ b/dd-apps/docker/nextcloud/nc_mail/lib/Db/MailAccountMapper.php
@@ -0,0 +1,188 @@
+
+ * @author Christoph Wurst
+ * @author Lukas Reschke
+ * @author Thomas Mรผller
+ *
+ * Mail
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\Mail\Db;
+
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Db\MultipleObjectsReturnedException;
+use OCP\AppFramework\Db\QBMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+use OCP\IUser;
+
+/**
+ * @template-extends QBMapper
+ */
+class MailAccountMapper extends QBMapper {
+
+ /**
+ * @param IDBConnection $db
+ */
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'mail_accounts');
+ }
+
+ /** Finds an Mail Account by id
+ *
+ * @param string $userId
+ * @param int $accountId
+ *
+ * @return MailAccount
+ *
+ * @throws DoesNotExistException
+ */
+ public function find(string $userId, int $accountId): MailAccount {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
+ ->andWhere($qb->expr()->eq('id', $qb->createNamedParameter($accountId)));
+
+ return $this->findEntity($query);
+ }
+
+ /**
+ * Finds an mail account by id
+ *
+ * @return MailAccount
+ * @throws DoesNotExistException
+ */
+ public function findById(int $id): MailAccount {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
+
+ return $this->findEntity($query);
+ }
+
+ /**
+ * Finds all Mail Accounts by user id existing for this user
+ *
+ * @param string $userId the id of the user that we want to find
+ *
+ * @return MailAccount[]
+ */
+ public function findByUserId(string $userId): array {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
+
+ return $this->findEntities($query);
+ }
+ /**
+ * Finds an mail account by user id and email address
+ *
+ * @return MailAccount
+ * @throws DoesNotExistException
+ */
+ public function findByUserIdAndEmail(string $userId, string $email): MailAccount {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->select('*')
+ ->from($this->getTableName())
+ ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR))
+ ->andWhere($qb->expr()->eq('email', $qb->createNamedParameter($email, IQueryBuilder::PARAM_STR), IQueryBuilder::PARAM_STR));
+
+ return $this->findEntity($query);
+ }
+
+ /**
+ * @throws DoesNotExistException
+ * @throws MultipleObjectsReturnedException
+ */
+ public function findProvisionedAccount(IUser $user): MailAccount {
+ $qb = $this->db->getQueryBuilder();
+
+ $query = $qb
+ ->select('*')
+ ->from($this->getTableName())
+ ->where(
+ $qb->expr()->eq('user_id', $qb->createNamedParameter($user->getUID())),
+ $qb->expr()->isNotNull('provisioning_id')
+ );
+
+ return $this->findEntity($query);
+ }
+
+ /**
+ * Saves an User Account into the database
+ *
+ * @param MailAccount $account
+ *
+ * @return MailAccount
+ */
+ public function save(MailAccount $account): MailAccount {
+ if ($account->getId() === null) {
+ return $this->insert($account);
+ }
+
+ return $this->update($account);
+ }
+
+ public function deleteProvisionedAccounts(int $provisioningId): void {
+ $qb = $this->db->getQueryBuilder();
+
+ $delete = $qb->delete($this->getTableName())
+ ->where($qb->expr()->eq('provisioning_id', $qb->createNamedParameter($provisioningId, IQueryBuilder::PARAM_INT)));
+
+ $delete->execute();
+ }
+
+ public function deleteProvisionedAccountsByUid(string $uid): void {
+ $qb = $this->db->getQueryBuilder();
+
+ $delete = $qb->delete($this->getTableName())
+ ->where(
+ $qb->expr()->eq('user_id', $qb->createNamedParameter($uid)),
+ $qb->expr()->isNotNull('provisioning_id')
+ );
+
+ $delete->execute();
+ }
+
+ public function getAllAccounts(): array {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->select('*')
+ ->from($this->getTableName());
+
+ return $this->findEntities($query);
+ }
+
+ public function getAllUserIdsWithAccounts(): array {
+ $qb = $this->db->getQueryBuilder();
+ $query = $qb
+ ->selectDistinct('user_id')
+ ->from($this->getTableName());
+
+ return $this->findEntities($query);
+ }
+}
diff --git a/dd-ctl b/dd-ctl
index 1412e2b..87da8e0 100755
--- a/dd-ctl
+++ b/dd-ctl
@@ -306,6 +306,12 @@ setup_nextcloud(){
EOF
done
+ # Temporary patch while upstream lands our changes
+ # See: https://github.com/nextcloud/mail/pull/6908
+ for f in appinfo/info.xml lib/Command/UpdateAccount.php lib/Db/MailAccountMapper.php; do
+ install -m 0644 -o 82 -g 82 "dd-apps/docker/nextcloud/nc_mail/$f" "${SRC_FOLDER}/nextcloud/custom_apps/mail/$f"
+ done
+
# Custom forms
docker exec dd-apps-nextcloud-app apk add git npm composer
docker exec -u www-data dd-apps-nextcloud-app rm -rf /var/www/html/custom_apps/forms