1<?php 2 3declare(strict_types=1); 4 5/** 6 * @author Daniel Kesselberg <mail@danielkesselberg.de> 7 * 8 * Mail 9 * 10 * This code is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Affero General Public License, version 3, 12 * as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Affero General Public License for more details. 18 * 19 * You should have received a copy of the GNU Affero General Public License, version 3, 20 * along with this program. If not, see <http://www.gnu.org/licenses/> 21 * 22 */ 23 24namespace OCA\Mail\Controller; 25 26use Horde\ManageSieve\Exception as ManagesieveException; 27use OCA\Mail\AppInfo\Application; 28use OCA\Mail\Db\MailAccountMapper; 29use OCA\Mail\Exception\ClientException; 30use OCA\Mail\Exception\CouldNotConnectException; 31use OCA\Mail\Service\AccountService; 32use OCA\Mail\Sieve\SieveClientFactory; 33use OCP\AppFramework\Controller; 34use OCP\AppFramework\Db\DoesNotExistException; 35use OCP\AppFramework\Http\JSONResponse; 36use OCP\IRequest; 37use OCP\Security\ICrypto; 38 39class SieveController extends Controller { 40 41 /** @var AccountService */ 42 private $accountService; 43 44 /** @var MailAccountMapper */ 45 private $mailAccountMapper; 46 47 /** @var SieveClientFactory */ 48 private $sieveClientFactory; 49 50 /** @var string */ 51 private $currentUserId; 52 53 /** @var ICrypto */ 54 private $crypto; 55 56 /** 57 * AccountsController constructor. 58 * 59 * @param IRequest $request 60 * @param string $UserId 61 * @param AccountService $accountService 62 * @param MailAccountMapper $mailAccountMapper 63 * @param SieveClientFactory $sieveClientFactory 64 * @param ICrypto $crypto 65 */ 66 public function __construct(IRequest $request, 67 string $UserId, 68 AccountService $accountService, 69 MailAccountMapper $mailAccountMapper, 70 SieveClientFactory $sieveClientFactory, 71 ICrypto $crypto 72 ) { 73 parent::__construct(Application::APP_ID, $request); 74 $this->currentUserId = $UserId; 75 $this->accountService = $accountService; 76 $this->mailAccountMapper = $mailAccountMapper; 77 $this->sieveClientFactory = $sieveClientFactory; 78 $this->crypto = $crypto; 79 } 80 81 /** 82 * @NoAdminRequired 83 * @TrapError 84 * 85 * @param int $id account id 86 * 87 * @return JSONResponse 88 * 89 * @throws CouldNotConnectException 90 * @throws ClientException 91 */ 92 public function getActiveScript(int $id): JSONResponse { 93 $sieve = $this->getClient($id); 94 95 $scriptName = $sieve->getActive(); 96 if ($scriptName === null) { 97 $script = ''; 98 } else { 99 $script = $sieve->getScript($scriptName); 100 } 101 102 return new JSONResponse([ 103 'scriptName' => $scriptName, 104 'script' => $script, 105 ]); 106 } 107 108 /** 109 * @NoAdminRequired 110 * @TrapError 111 * 112 * @param int $id account id 113 * @param string $script 114 * 115 * @return JSONResponse 116 * 117 * @throws ClientException 118 * @throws CouldNotConnectException 119 * @throws ManagesieveException 120 */ 121 public function updateActiveScript(int $id, string $script): JSONResponse { 122 $sieve = $this->getClient($id); 123 124 $scriptName = $sieve->getActive() ?? 'nextcloud'; 125 $sieve->installScript($scriptName, $script, true); 126 127 return new JSONResponse(); 128 } 129 130 /** 131 * @NoAdminRequired 132 * @TrapError 133 * 134 * @param int $id account id 135 * @param bool $sieveEnabled 136 * @param string $sieveHost 137 * @param int $sievePort 138 * @param string $sieveUser 139 * @param string $sievePassword 140 * @param string $sieveSslMode 141 * 142 * @return JSONResponse 143 * 144 * @throws CouldNotConnectException 145 * @throws DoesNotExistException 146 */ 147 public function updateAccount(int $id, 148 bool $sieveEnabled, 149 string $sieveHost, 150 int $sievePort, 151 string $sieveUser, 152 string $sievePassword, 153 string $sieveSslMode 154 ): JSONResponse { 155 $mailAccount = $this->mailAccountMapper->find($this->currentUserId, $id); 156 157 if ($sieveEnabled === false) { 158 $mailAccount->setSieveEnabled(false); 159 $mailAccount->setSieveHost(null); 160 $mailAccount->setSievePort(null); 161 $mailAccount->setSieveUser(null); 162 $mailAccount->setSievePassword(null); 163 $mailAccount->setSieveSslMode(null); 164 165 $this->mailAccountMapper->save($mailAccount); 166 return new JSONResponse(['sieveEnabled' => $mailAccount->isSieveEnabled()]); 167 } 168 169 if (empty($sieveUser)) { 170 $sieveUser = $mailAccount->getInboundUser(); 171 } 172 173 if (empty($sievePassword)) { 174 $sievePassword = $mailAccount->getInboundPassword(); 175 } else { 176 $sievePassword = $this->crypto->encrypt($sievePassword); 177 } 178 179 try { 180 $this->sieveClientFactory->createClient($sieveHost, $sievePort, $sieveUser, $sievePassword, $sieveSslMode); 181 } catch (ManagesieveException $e) { 182 throw CouldNotConnectException::create($e, 'ManageSieve', $sieveHost, $sievePort); 183 } 184 185 $mailAccount->setSieveEnabled(true); 186 $mailAccount->setSieveHost($sieveHost); 187 $mailAccount->setSievePort($sievePort); 188 $mailAccount->setSieveUser($mailAccount->getInboundUser() === $sieveUser ? null : $sieveUser); 189 $mailAccount->setSievePassword($mailAccount->getInboundPassword() === $sievePassword ? null : $sievePassword); 190 $mailAccount->setSieveSslMode($sieveSslMode); 191 192 $this->mailAccountMapper->save($mailAccount); 193 return new JSONResponse(['sieveEnabled' => $mailAccount->isSieveEnabled()]); 194 } 195 196 /** 197 * @param int $id 198 * 199 * @return \Horde\ManageSieve 200 * 201 * @throws ClientException 202 * @throws CouldNotConnectException 203 */ 204 protected function getClient(int $id): \Horde\ManageSieve { 205 $account = $this->accountService->find($this->currentUserId, $id); 206 207 if (!$account->getMailAccount()->isSieveEnabled()) { 208 throw new CouldNotConnectException('ManageSieve is disabled.'); 209 } 210 211 try { 212 $sieve = $this->sieveClientFactory->getClient($account); 213 } catch (ManagesieveException $e) { 214 throw CouldNotConnectException::create($e, 'ManageSieve', $account->getMailAccount()->getSieveHost(), $account->getMailAccount()->getSievePort()); 215 } 216 217 return $sieve; 218 } 219} 220