Completed
Pull Request — master (#1523)
by
unknown
06:29
created

AccountsController::update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * @author Christoph Wurst <[email protected]>
4
 * @author Christoph Wurst <[email protected]>
5
 * @author Jan-Christoph Borchardt <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Robin McCorkell <[email protected]>
8
 * @author Thomas Müller <[email protected]>
9
 *
10
 * ownCloud - Mail
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
26
namespace OCA\Mail\Controller;
27
28
use Exception;
29
use Horde_Exception;
30
use Horde_Imap_Client;
31
use OCA\Mail\Account;
32
use OCA\Mail\Db\MailAccount;
33
use OCA\Mail\Model\Message;
34
use OCA\Mail\Model\ReplyMessage;
35
use OCA\Mail\Service\AccountService;
36
use OCA\Mail\Service\AutoCompletion\AddressCollector;
37
use OCA\Mail\Service\AutoConfig\AutoConfig;
38
use OCA\Mail\Service\Logger;
39
use OCA\Mail\Service\UnifiedAccount;
40
use OCP\AppFramework\Controller;
41
use OCP\AppFramework\Db\DoesNotExistException;
42
use OCP\AppFramework\Http;
43
use OCP\AppFramework\Http\JSONResponse;
44
use OCP\AppFramework\Http\Response;
45
use OCP\Files\File;
46
use OCP\Files\Folder;
47
use OCP\IL10N;
48
use OCP\IRequest;
49
use OCP\Security\ICrypto;
50
use OCA\Mail\Service\AliasesService;
51
52
class AccountsController extends Controller {
53
54
	/** @var AccountService */
55
	private $accountService;
56
57
	/** @var string */
58
	private $currentUserId;
59
60
	/** @var AutoConfig */
61
	private $autoConfig;
62
63
	/** @var Folder */
64
	private $userFolder;
65
66
	/** @var Logger */
67
	private $logger;
68
69
	/** @var IL10N */
70
	private $l10n;
71
72
	/** @var ICrypto */
73
	private $crypto;
74
75
	/** @var AddressCollector  */
76
	private $addressCollector;
77
78
	private $aliasesService;
79
80
	/**
81
	 * @param string $appName
82
	 * @param IRequest $request
83
	 * @param AccountService $accountService
84
	 * @param $UserId
85
	 * @param $userFolder
86
	 * @param AutoConfig $autoConfig
87
	 * @param Logger $logger
88
	 * @param IL10N $l10n
89
	 * @param ICrypto $crypto
90
	 */
91 15
	public function __construct($appName,
92
		IRequest $request,
93
		AccountService $accountService,
94
		$UserId,
95
		$userFolder,
96
		AutoConfig $autoConfig,
97
		Logger $logger,
98
		IL10N $l10n,
99
		ICrypto $crypto,
100
		AddressCollector $addressCollector,
101
		AliasesService $aliasesService
102
	) {
103 15
		parent::__construct($appName, $request);
104 15
		$this->accountService = $accountService;
105 15
		$this->currentUserId = $UserId;
106 15
		$this->userFolder = $userFolder;
107 15
		$this->autoConfig = $autoConfig;
108 15
		$this->logger = $logger;
109 15
		$this->l10n = $l10n;
110 15
		$this->crypto = $crypto;
111 15
		$this->addressCollector = $addressCollector;
112 15
		$this->aliasesService = $aliasesService;
113 15
	}
114
115
	/**
116
	 * @NoAdminRequired
117
	 * @NoCSRFRequired
118
	 *
119
	 * @return JSONResponse
120
	 */
121 1
	public function index() {
122 1
		$mailAccounts = $this->accountService->findByUserId($this->currentUserId);
123
124 1
		$json = [];
125 1
		foreach ($mailAccounts as $mailAccount) {
126 1
			$json[] = $mailAccount->getConfiguration();
127 1
		}
128 1
		foreach ($json as $key => $mailAccount) {
129 1
			$json[$key]['aliases'] = $this->aliasesService->findAll($mailAccount['accountId'], $this->currentUserId);
130
		}
131
		return new JSONResponse($json);
132
	}
133
134
	/**
135
	 * @NoAdminRequired
136
	 *
137
	 * @param int $accountId
138
	 * @return JSONResponse
139
	 */
140 2
	public function show($accountId) {
141
		try {
142 2
			$account = $this->accountService->find($this->currentUserId, $accountId);
143
144 2
			return new JSONResponse($account->getConfiguration());
145 1
		} catch (DoesNotExistException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\AppFramework\Db\DoesNotExistException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
146 1
			return new JSONResponse([], 404);
147
		}
148
	}
149
150
	/**
151
	 * @NoAdminRequired
152
	 */
153
	public function update() {
154
		$response = new Response();
155
		$response->setStatus(Http::STATUS_NOT_IMPLEMENTED);
156
		return $response;
157
	}
158
159
	/**
160
	 * @NoAdminRequired
161
	 *
162
	 * @param int $accountId
163
	 * @return JSONResponse
164
	 */
165 2
	public function destroy($accountId) {
166
		try {
167 2
			$this->accountService->delete($this->currentUserId, $accountId);
168
169 1
			return new JSONResponse();
170 1
		} catch (DoesNotExistException $e) {
0 ignored issues
show
Bug introduced by
The class OCP\AppFramework\Db\DoesNotExistException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
171 1
			return new JSONResponse();
172
		}
173
	}
174
175
	/**
176
	 * @NoAdminRequired
177
	 *
178
	 * @param string $accountName
179
	 * @param string $emailAddress
180
	 * @param string $password
181
	 * @param string $imapHost
182
	 * @param int $imapPort
183
	 * @param string $imapSslMode
184
	 * @param string $imapUser
185
	 * @param string $imapPassword
186
	 * @param string $smtpHost
187
	 * @param int $smtpPort
188
	 * @param string $smtpSslMode
189
	 * @param string $smtpUser
190
	 * @param string $smtpPassword
191
	 * @param bool $autoDetect
192
	 * @return JSONResponse
193
	 */
194 2
	public function create($accountName, $emailAddress, $password,
195
		$imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword,
196
		$smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword,
197
		$autoDetect) {
198
		try {
199 2
			if ($autoDetect) {
200 2
				$this->logger->info('setting up auto detected account');
201 2
				$newAccount = $this->autoConfig->createAutoDetected($emailAddress, $password, $accountName);
202 2
			} else {
203
				$this->logger->info('Setting up manually configured account');
204
				$newAccount = new MailAccount([
205
					'accountName'  => $accountName,
206
					'emailAddress' => $emailAddress,
207
					'imapHost'     => $imapHost,
208
					'imapPort'     => $imapPort,
209
					'imapSslMode'  => $imapSslMode,
210
					'imapUser'     => $imapUser,
211
					'imapPassword' => $imapPassword,
212
					'smtpHost'     => $smtpHost,
213
					'smtpPort'     => $smtpPort,
214
					'smtpSslMode'  => $smtpSslMode,
215
					'smtpUser'     => $smtpUser,
216
					'smtpPassword' => $smtpPassword
217
				]);
218
				$newAccount->setUserId($this->currentUserId);
219
				$newAccount->setInboundPassword(
220
					$this->crypto->encrypt(
221
						$newAccount->getInboundPassword()
222
					)
223
				);
224
				$newAccount->setOutboundPassword(
225
					$this->crypto->encrypt(
226
						$newAccount->getOutboundPassword()
227
					)
228
				);
229
230
				$a = new Account($newAccount);
231
				$this->logger->debug('Connecting to account {account}', ['account' => $newAccount->getEmail()]);
232
				$a->testConnectivity();
233
			}
234
235 2
			if ($newAccount) {
236 1
				$this->accountService->save($newAccount);
237 1
				$this->logger->debug("account created " . $newAccount->getId());
238 1
				return new JSONResponse(
239 1
					['data' => ['id' => $newAccount->getId()]],
240 1
					Http::STATUS_CREATED);
241
			}
242 1
		} catch (Exception $ex) {
243
			$this->logger->error('Creating account failed: ' . $ex->getMessage());
244
			return new JSONResponse(
245
				array('message' => $this->l10n->t('Creating account failed: ') . $ex->getMessage()),
246
				HTTP::STATUS_BAD_REQUEST);
247
		}
248
249 1
		$this->logger->info('Auto detect failed');
250 1
		return new JSONResponse(
251 1
			array('message' => $this->l10n->t('Auto detect failed. Please use manual mode.')),
252 1
			HTTP::STATUS_BAD_REQUEST);
253
	}
254
255
	/**
256
	 * @NoAdminRequired
257
	 *
258
	 * @param int $accountId
259
	 * @param string $folderId
260
	 * @param string $subject
261
	 * @param string $body
262
	 * @param string $to
263
	 * @param string $cc
264
	 * @param string $bcc
265
	 * @param int $draftUID
266
	 * @param string $messageId
267
	 * @param mixed $attachments
268
	 * @return JSONResponse
269
	 */
270 4
	public function send($accountId, $folderId, $subject, $body, $to, $cc,
271
		$bcc, $draftUID, $messageId, $attachments, $aliasId) {
272 4
		$account = $this->accountService->find($this->currentUserId, $accountId);
273 4
		$alias = $aliasId ? $this->aliasesService->find($aliasId, $this->currentUserId) : null;
274 4
		if ($account instanceof UnifiedAccount) {
275 2
			list($account, $folderId, $messageId) = $account->resolve($messageId);
276 2
		}
277 4
		if (!$account instanceof Account) {
278
			return new JSONResponse(
279
				['message' => 'Invalid account'],
280
				Http::STATUS_BAD_REQUEST
281
			);
282
		}
283
284 4
		$mailbox = null;
285 4
		if (!is_null($folderId) && !is_null($messageId)) {
286
			// Reply
287 2
			$message = $account->newReplyMessage();
288
289 2
			$mailbox = $account->getMailbox(base64_decode($folderId));
290 2
			$repliedMessage = $mailbox->getMessage($messageId);
291
292 2
			if (is_null($subject)) {
293
				// No subject set – use the original one
294
				$message->setSubject($repliedMessage->getSubject());
295
			} else {
296 2
				$message->setSubject($subject);
297
			}
298
299 2
			if (is_null($to)) {
300
				$message->setTo(Message::parseAddressList($repliedMessage->getToList()));
0 ignored issues
show
Documentation introduced by
$repliedMessage->getToList() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
301
			} else {
302 2
				$message->setTo(Message::parseAddressList($to));
303
			}
304
305 2
			$message->setRepliedMessage($repliedMessage);
306 2
		} else {
307
			// New message
308 2
			$message = $account->newMessage();
309 2
			$message->setTo(Message::parseAddressList($to));
310 2
			$message->setSubject($subject ? : '');
311
		}
312
313 4
		$account->setAlias($alias);
0 ignored issues
show
Documentation introduced by
$alias is of type array<integer,object<OCA\Mail\Db\Alias>>|null, but the function expects a object<OCA\Mail\Db\Alias>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
314 4
		$message->setFrom($alias ? $alias->alias : $account->getEMailAddress());
315 4
		$message->setCC(Message::parseAddressList($cc));
316 4
		$message->setBcc(Message::parseAddressList($bcc));
317 4
		$message->setContent($body);
318
319 4
		if (is_array($attachments)) {
320 4
			foreach($attachments as $attachment) {
321 4
				$fileName = $attachment['fileName'];
322 4
				if ($this->userFolder->nodeExists($fileName)) {
323 4
					$f = $this->userFolder->get($fileName);
324 4
					if ($f instanceof File) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
325 4
						$message->addAttachmentFromFiles($f);
326 4
					}
327 4
				}
328 4
			}
329 4
		}
330
331
		try {
332 4
			$account->sendMessage($message, $draftUID);
333
334
			// in case of reply we flag the message as answered
335 4
			if ($message instanceof ReplyMessage) {
336 2
				$mailbox->setMessageFlag($messageId, Horde_Imap_Client::FLAG_ANSWERED, true);
337 2
			}
338
339
			// Collect mail addresses
340
			try {
341 4
				$addresses = array_merge($message->getToList(), $message->getCCList(), $message->getBCCList());
342 4
				$this->addressCollector->addAddresses($addresses);
343 4
			} catch (Exception $e) {
344 1
				$this->logger->error("Error while collecting mail addresses: " . $e->getMessage());
345
			}
346 4
		} catch (Horde_Exception $ex) {
0 ignored issues
show
Bug introduced by
The class Horde_Exception does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
347
			$this->logger->error('Sending mail failed: ' . $ex->getMessage());
348
			return new JSONResponse(
349
				array('message' => $ex->getMessage()),
350
				Http::STATUS_INTERNAL_SERVER_ERROR
351
			);
352
		}
353
354 4
		return new JSONResponse();
355
	}
356
357
	/**
358
	 * @NoAdminRequired
359
	 * 
360
	 * @param int $accountId
361
	 * @param string $subject
362
	 * @param string $body
363
	 * @param string $to
364
	 * @param string $cc
365
	 * @param string $bcc
366
	 * @param int $uid
367
	 * @param string $messageId
368
	 * @return JSONResponse
369
	 */
370 4
	public function draft($accountId, $subject, $body, $to, $cc, $bcc, $uid, $messageId) {
371 4
		if (is_null($uid)) {
372 2
			$this->logger->info("Saving a new draft in account <$accountId>");
373 2
		} else {
374 2
			$this->logger->info("Updating draft <$uid> in account <$accountId>");
375
		}
376
377 4
		$account = $this->accountService->find($this->currentUserId, $accountId);
378 4
		if ($account instanceof UnifiedAccount) {
379 2
			list($account) = $account->resolve($messageId);
380 2
		}
381 4
		if (!$account instanceof Account) {
382
			return new JSONResponse(
383
				array('message' => 'Invalid account'),
384
				Http::STATUS_BAD_REQUEST
385
			);
386
		}
387
388 4
		$message = $account->newMessage();
389 4
		$message->setTo(Message::parseAddressList($to));
390 4
		$message->setSubject($subject ? : '');
391 4
		$message->setFrom($account->getEMailAddress());
392 4
		$message->setCC(Message::parseAddressList($cc));
393 4
		$message->setBcc(Message::parseAddressList($bcc));
394 4
		$message->setContent($body);
395
396
		// create transport and save message
397
		try {
398 4
			$newUID = $account->saveDraft($message, $uid);
399 4
		} catch (Horde_Exception $ex) {
0 ignored issues
show
Bug introduced by
The class Horde_Exception does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
400
			$this->logger->error('Saving draft failed: ' . $ex->getMessage());
401
			return new JSONResponse(
402
				[
403
					'message' => $ex->getMessage()
404
				],
405
				Http::STATUS_INTERNAL_SERVER_ERROR
406
			);
407
		}
408
409 4
		return new JSONResponse([
410
			'uid' => $newUID
411 4
		]);
412
	}
413
414
}
415