Completed
Pull Request — master (#1276)
by Christoph
02:50
created

AccountsController::autoComplete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * ownCloud - Mail app
4
 *
5
 * @author Sebastian Schmid
6
 * @copyright 2013 Sebastian Schmid [email protected]
7
 *
8
 * @author Christoph Wurst <[email protected]>
9
 * @copyright Christoph Wurst 2015
10
 *
11
 * This library is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
13
 * License as published by the Free Software Foundation; either
14
 * version 3 of the License, or any later version.
15
 *
16
 * This library 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 Lesser General Public
22
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
namespace OCA\Mail\Controller;
27
28
use Horde_Imap_Client;
29
use OCA\Mail\Account;
30
use OCA\Mail\Db\MailAccount;
31
use OCA\Mail\Model\Message;
32
use OCA\Mail\Model\ReplyMessage;
33
use OCA\Mail\Service\AccountService;
34
use OCA\Mail\Service\AutoConfig\AutoConfig;
35
use OCA\Mail\Service\Logger;
36
use OCA\Mail\Service\UnifiedAccount;
37
use OCP\AppFramework\Controller;
38
use OCP\AppFramework\Db\DoesNotExistException;
39
use OCP\AppFramework\Http\JSONResponse;
40
use OCP\AppFramework\Http\Response;
41
use OCP\AppFramework\Http;
42
use OCP\Files\File;
43
use OCP\IL10N;
44
use OCP\ILogger;
45
use OCP\IRequest;
46
use OCP\Security\ICrypto;
47
48
class AccountsController extends Controller {
49
50
	/** @var AccountService */
51
	private $accountService;
52
53
	/** @var string */
54
	private $currentUserId;
55
56
	/** @var AutoConfig */
57
	private $autoConfig;
58
59
	/** @var \OCP\Files\Folder */
60
	private $userFolder;
61
62
	/** @var ILogger */
63
	private $logger;
64
65
	/** @var IL10N */
66
	private $l10n;
67
68
	/** @var ICrypto */
69
	private $crypto;
70
71
	/**
72
	 * @param string $appName
73
	 * @param IRequest $request
74
	 * @param AccountService $accountService
75
	 * @param $UserId
76
	 * @param $userFolder
77
	 * @param AutoConfig $autoConfig
78
	 * @param Logger $logger
79
	 * @param IL10N $l10n
80
	 * @param ICrypto $crypto
81
	 */
82 View Code Duplication
	public function __construct($appName,
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
83
		IRequest $request,
84
		AccountService $accountService,
85
		$UserId,
86
		$userFolder,
87 16
		AutoConfig $autoConfig,
88
		Logger $logger,
89
		IL10N $l10n,
90
		ICrypto $crypto
91
	) {
92
		parent::__construct($appName, $request);
93
		$this->accountService = $accountService;
94
		$this->currentUserId = $UserId;
95
		$this->userFolder = $userFolder;
96
		$this->autoConfig = $autoConfig;
97
		$this->logger = $logger;
98 16
		$this->l10n = $l10n;
99 16
		$this->crypto = $crypto;
100 16
	}
101 16
102 16
	/**
103 16
	 * @NoAdminRequired
104 16
	 * @NoCSRFRequired
105 16
	 *
106 16
	 * @return JSONResponse
107 16
	 */
108
	public function index() {
109
		$mailAccounts = $this->accountService->findByUserId($this->currentUserId);
110
111
		$json = [];
112
		foreach ($mailAccounts as $mailAccount) {
113
			$json[] = $mailAccount->getConfiguration();
114
		}
115 1
116 1
		return new JSONResponse($json);
117
	}
118 1
119 1
	/**
120 1
	 * @NoAdminRequired
121 1
	 *
122
	 * @param int $accountId
123 1
	 * @return JSONResponse
124
	 */
125
	public function show($accountId) {
126
		try {
127
			$account = $this->accountService->find($this->currentUserId, $accountId);
128
129
			return new JSONResponse($account->getConfiguration());
130
		} 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...
131
			return new JSONResponse([], 404);
132 2
		}
133
	}
134 2
135
	/**
136 2
	 * @NoAdminRequired
137 1
	 */
138 1
	public function update() {
139
		$response = new Response();
140
		$response->setStatus(Http::STATUS_NOT_IMPLEMENTED);
141
		return $response;
142
	}
143
144
	/**
145
	 * @NoAdminRequired
146
	 *
147
	 * @param int $accountId
148
	 * @return JSONResponse
149
	 */
150
	public function destroy($accountId) {
151
		try {
152
			$this->accountService->delete($this->currentUserId, $accountId);
153
154
			return new JSONResponse();
155
		} 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...
156
			return new JSONResponse();
157 2
		}
158
	}
159 2
160
	/**
161 1
	 * @NoAdminRequired
162 1
	 *
163 1
	 * @param string $accountName
164
	 * @param string $emailAddress
165
	 * @param string $password
166
	 * @param string $imapHost
167
	 * @param int $imapPort
168
	 * @param string $imapSslMode
169
	 * @param string $imapUser
170
	 * @param string $imapPassword
171
	 * @param string $smtpHost
172
	 * @param int $smtpPort
173
	 * @param string $smtpSslMode
174
	 * @param string $smtpUser
175
	 * @param string $smtpPassword
176
	 * @param bool $autoDetect
177
	 * @return JSONResponse
178
	 */
179
	public function create($accountName, $emailAddress, $password,
180
		$imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword,
181
		$smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword,
182
		$autoDetect) {
183
		try {
184
			if ($autoDetect) {
185
				$this->logger->info('setting up auto detected account');
186 2
				$newAccount = $this->autoConfig->createAutoDetected($emailAddress, $password, $accountName);
187
			} else {
188
				$this->logger->info('Setting up manually configured account');
189
				$newAccount = new MailAccount([
190
					'accountName'  => $accountName,
191 2
					'emailAddress' => $emailAddress,
192 2
					'imapHost'     => $imapHost,
193 2
					'imapPort'     => $imapPort,
194 2
					'imapSslMode'  => $imapSslMode,
195
					'imapUser'     => $imapUser,
196
					'imapPassword' => $imapPassword,
197
					'smtpHost'     => $smtpHost,
198
					'smtpPort'     => $smtpPort,
199
					'smtpSslMode'  => $smtpSslMode,
200
					'smtpUser'     => $smtpUser,
201
					'smtpPassword' => $smtpPassword
202
				]);
203
				$newAccount->setUserId($this->currentUserId);
204
				$newAccount->setInboundPassword(
205
					$this->crypto->encrypt(
206
						$newAccount->getInboundPassword()
207
					)
208
				);
209
				$newAccount->setOutboundPassword(
210
					$this->crypto->encrypt(
211
						$newAccount->getOutboundPassword()
212
					)
213
				);
214
215
				$a = new Account($newAccount);
216
				$this->logger->debug('Connecting to account {account}', ['account' => $newAccount->getEmail()]);
217
				$a->testConnectivity();
218
			}
219
220
			if ($newAccount) {
221
				$this->accountService->save($newAccount);
222
				$this->logger->debug("account created " . $newAccount->getId());
223
				return new JSONResponse(
224
					['data' => ['id' => $newAccount->getId()]],
225
					Http::STATUS_CREATED);
226
			}
227 2
		} catch (\Exception $ex) {
228 1
			$this->logger->error('Creating account failed: ' . $ex->getMessage());
229 1
			return new JSONResponse(
230 1
				array('message' => $this->l10n->t('Creating account failed: ') . $ex->getMessage()),
231 1
				HTTP::STATUS_BAD_REQUEST);
232 1
		}
233
234 1
		$this->logger->info('Auto detect failed');
235
		return new JSONResponse(
236
			array('message' => $this->l10n->t('Auto detect failed. Please use manual mode.')),
237
			HTTP::STATUS_BAD_REQUEST);
238
	}
239
240
	/**
241 1
	 * @NoAdminRequired
242 1
	 *
243 1
	 * @param int $accountId
244 1
	 * @param string $folderId
245
	 * @param string $subject
246
	 * @param string $body
247
	 * @param string $to
248
	 * @param string $cc
249
	 * @param string $bcc
250
	 * @param int $draftUID
251
	 * @param string $messageId
252
	 * @param mixed $attachments
253
	 * @return JSONResponse
254
	 */
255
	public function send($accountId, $folderId, $subject, $body, $to, $cc,
256
		$bcc, $draftUID, $messageId, $attachments) {
257
		$account = $this->accountService->find($this->currentUserId, $accountId);
258
		if ($account instanceof UnifiedAccount) {
259
			list($account, $folderId, $messageId) = $account->resolve($messageId);
260
		}
261
		if (!$account instanceof Account) {
262 4
			return new JSONResponse(
263
				['message' => 'Invalid account'],
264 4
				Http::STATUS_BAD_REQUEST
265 4
			);
266 2
		}
267 2
268 4
		$mailbox = null;
269
		if (!is_null($folderId) && !is_null($messageId)) {
270
			// Reply
271
			$message = $account->newReplyMessage();
272
273
			$mailbox = $account->getMailbox(base64_decode($folderId));
274
			$repliedMessage = $mailbox->getMessage($messageId);
275 4
276 4
			if (is_null($subject)) {
277
				// No subject set – use the original one
278 2
				$message->setSubject($repliedMessage->getSubject());
279
			} else {
280 2
				$message->setSubject($subject);
281 2
			}
282
283 2
			if (is_null($to)) {
284
				$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...
285
			} else {
286
				$message->setTo(Message::parseAddressList($to));
287 2
			}
288
289
			$message->setRepliedMessage($repliedMessage);
290 2
		} else {
291
			// New message
292
			$message = $account->newMessage();
293 2
			$message->setTo(Message::parseAddressList($to));
294
			$message->setSubject($subject ? : '');
295
		}
296 2
297 2
		$message->setFrom($account->getEMailAddress());
298
		$message->setCC(Message::parseAddressList($cc));
299 2
		$message->setBcc(Message::parseAddressList($bcc));
300 2
		$message->setContent($body);
301 2
302
		if (is_array($attachments)) {
303
			foreach($attachments as $attachment) {
304 4
				$fileName = $attachment['fileName'];
305 4
				if ($this->userFolder->nodeExists($fileName)) {
306 4
					$f = $this->userFolder->get($fileName);
307 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...
308
						$message->addAttachmentFromFiles($f);
309 4
					}
310 4
				}
311 4
			}
312 4
		}
313 4
314 4
		try {
315 4
			$account->sendMessage($message, $draftUID);
316 4
317 4
			// in case of reply we flag the message as answered
318 4
			if ($message instanceof ReplyMessage) {
319 4
				$mailbox->setMessageFlag($messageId, Horde_Imap_Client::FLAG_ANSWERED, true);
320
			}
321
		} catch (\Horde_Exception $ex) {
0 ignored issues
show
Bug introduced by
The class Horde_Exception 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...
322 4
			$this->logger->error('Sending mail failed: ' . $ex->getMessage());
323
			return new JSONResponse(
324
				array('message' => $ex->getMessage()),
325 4
				Http::STATUS_INTERNAL_SERVER_ERROR
326 2
			);
327 2
		}
328 4
329
		return new JSONResponse();
330
	}
331
332
	/**
333
	 * @NoAdminRequired
334
	 * 
335
	 * @param int $accountId
336 4
	 * @param string $subject
337
	 * @param string $body
338
	 * @param string $to
339
	 * @param string $cc
340
	 * @param string $bcc
341
	 * @param int $uid
342
	 * @param string $messageId
343
	 * @return JSONResponse
344
	 */
345
	public function draft($accountId, $subject, $body, $to, $cc, $bcc, $uid, $messageId) {
346
		if (is_null($uid)) {
347
			$this->logger->info("Saving a new draft in account <$accountId>");
348
		} else {
349
			$this->logger->info("Updating draft <$uid> in account <$accountId>");
350
		}
351
352 4
		$account = $this->accountService->find($this->currentUserId, $accountId);
353 4
		if ($account instanceof UnifiedAccount) {
354 2
			list($account) = $account->resolve($messageId);
355 2
		}
356 2
		if (!$account instanceof Account) {
357
			return new JSONResponse(
358
				array('message' => 'Invalid account'),
359 4
				Http::STATUS_BAD_REQUEST
360 4
			);
361 2
		}
362 2
363 4
		$message = $account->newMessage();
364
		$message->setTo(Message::parseAddressList($to));
365
		$message->setSubject($subject ? : '');
366
		$message->setFrom($account->getEMailAddress());
367
		$message->setCC(Message::parseAddressList($cc));
368
		$message->setBcc(Message::parseAddressList($bcc));
369
		$message->setContent($body);
370 4
371 4
		// create transport and save message
372 4
		try {
373 4
			$newUID = $account->saveDraft($message, $uid);
374 4
		} catch (\Horde_Exception $ex) {
0 ignored issues
show
Bug introduced by
The class Horde_Exception 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...
375 4
			$this->logger->error('Saving draft failed: ' . $ex->getMessage());
376 4
			return new JSONResponse(
377
				[
378
					'message' => $ex->getMessage()
379
				],
380 4
				Http::STATUS_INTERNAL_SERVER_ERROR
381 4
			);
382
		}
383
384
		return new JSONResponse([
385
			'uid' => $newUID
386
		]);
387
	}
388
389
}
390