Completed
Pull Request — master (#1038)
by René
06:51 queued 55s
created

MailService::resolveEmailAddress()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 17
ccs 0
cts 16
cp 0
rs 9.9666
cc 4
nc 6
nop 2
crap 20
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Vinzenz Rosenkranz <[email protected]>
4
 *
5
 * @author René Gieling <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
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
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Polls\Service;
25
26
use Exception;
27
28
use OCP\IUser;
29
use OCP\IUserManager;
30
use OCP\IGroupManager;
31
use OCP\IConfig;
32
use OCP\IURLGenerator;
33
use OCP\IL10N;
34
use OCP\L10N\IFactory;
35
use OCP\Mail\IMailer;
36
use OCP\Mail\IEMailTemplate;
37
38
use OCA\Polls\Db\SubscriptionMapper;
39
use OCA\Polls\Db\Subscription;
40
use OCA\Polls\Db\PollMapper;
41
use OCA\Polls\Db\Poll;
42
use OCA\Polls\Db\ShareMapper;
43
use OCA\Polls\Db\Share;
44
use OCA\Polls\Db\LogMapper;
45
46
class MailService {
47
48
	/** @var IUserManager */
49
	private $userManager;
50
51
	/** @var IGroupManager */
52
	private $groupManager;
53
54
	/** @var IConfig */
55
	private $config;
56
57
	/** @var IURLGenerator */
58
	private $urlGenerator;
59
60
	/** @var IL10N */
61
	private $trans;
62
63
	/** @var IFactory */
64
	private $transFactory;
65
66
	/** @var IMailer */
67
	private $mailer;
68
69
	/** @var SubscriptionMapper */
70
	private $subscriptionMapper;
71
72
	/** @var ShareMapper */
73
	private $shareMapper;
74
75
	/** @var PollMapper */
76
	private $pollMapper;
77
78
	/** @var LogMapper */
79
	private $logMapper;
80
81
	/**
82
	 * MailService constructor.
83
	 * @param IUserManager $userManager
84
	 * @param IGroupManager $groupManager
85
	 * @param IConfig $config
86
	 * @param IURLGenerator $urlGenerator
87
	 * @param IL10N $trans
88
	 * @param IFactory $transFactory
89
	 * @param IMailer $mailer
90
	 * @param SubscriptionMapper $subscriptionMapper
91
	 * @param ShareMapper $shareMapper
92
	 * @param PollMapper $pollMapper
93
	 * @param LogMapper $logMapper
94
	 */
95
96
	public function __construct(
97
		IUserManager $userManager,
98
		IGroupManager $groupManager,
99
		IConfig $config,
100
		IURLGenerator $urlGenerator,
101
		IL10N $trans,
102
		IFactory $transFactory,
103
		IMailer $mailer,
104
		ShareMapper $shareMapper,
105
		SubscriptionMapper $subscriptionMapper,
106
		PollMapper $pollMapper,
107
		LogMapper $logMapper
108
	) {
109
		$this->config = $config;
110
		$this->userManager = $userManager;
111
		$this->groupManager = $groupManager;
112
		$this->urlGenerator = $urlGenerator;
113
		$this->trans = $trans;
114
		$this->transFactory = $transFactory;
115
		$this->mailer = $mailer;
116
		$this->shareMapper = $shareMapper;
117
		$this->subscriptionMapper = $subscriptionMapper;
118
		$this->pollMapper = $pollMapper;
119
		$this->logMapper = $logMapper;
120
	}
121
122
123
	/**
124
	 * sendMail - Send eMail and evaluate recipient's mail address
125
	 * and displayname if $toUserId is a site user
126
	 * @param IEmailTemplate $emailTemplate
127
	 * @param String $toUserId
128
	 * @param String $toEmail
129
	 * @param String $toDisplayName
130
	 * @return String
131
	 */
132
133
	private function sendMail($emailTemplate, $toUserId = '', $toEmail = '', $toDisplayName = '') {
134
135
		if ($this->userManager->get($toUserId) instanceof IUser && !$toEmail) {
136
			$toEmail = \OC::$server->getConfig()->getUserValue($toUserId, 'settings', 'email');
137
			$toDisplayName = $this->userManager->get($toUserId)->getDisplayName();
138
		}
139
140
		if (!$toEmail || !filter_var($toEmail, FILTER_VALIDATE_EMAIL)) {
141
	   		throw new Exception('Invalid email address (' . $toEmail . ')');
142
		}
143
144
		try {
145
			$message = $this->mailer->createMessage();
146
			$message->setTo([$toEmail => $toDisplayName]);
147
			$message->useTemplate($emailTemplate);
148
			$this->mailer->send($message);
149
150
			return null;
151
152
		} catch (\Exception $e) {
153
			\OC::$server->getLogger()->logException($e, ['app' => 'polls']);
154
			throw $e;
155
		}
156
157
	}
158
159
160
	/**
161
	 * @param integer $pollId
162
	 * @param string $userId
163
	 * @return string
164
	 */
165
	public function resolveEmailAddress($pollId, $userId) {
166
		$contactsManager = \OC::$server->getContactsManager();
0 ignored issues
show
Unused Code introduced by
The assignment to $contactsManager is dead and can be removed.
Loading history...
167
168
		if ($this->userManager->get($userId) instanceof IUser) {
169
			return \OC::$server->getConfig()->getUserValue($userId, 'settings', 'email');
170
		}
171
172
		// if $userId is no site user, eval via shares
173
		try {
174
			$share = $this->shareMapper->findByPollAndUser($pollId, $userId);
175
			if ($share->getUserEmail()) {
176
				return $share->getUserEmail();
177
			}
178
		} catch (\Exception $e) {
179
			// catch silently
180
		}
181
		return $userId;
182
	}
183
184
185
	/**
186
	 * @param Share $share
187
	 * @param String $defaultLang
188
	 * @param String $skipUser
189
	 * @return Array $recipients
190
	 */
191
	private function getRecipientsByShare($share, $defaultLang = 'en', $skipUser = null) {
192
		$recipients = [];
193
		$contactsManager = \OC::$server->getContactsManager();
194
195
		if ($share->getType() === 'user') {
196
197
			$recipients[] = array(
198
				'userId' => $share->getUserId(),
199
				'eMailAddress' => \OC::$server->getConfig()->getUserValue($share->getUserId(), 'settings', 'email'),
200
				'displayName' => $this->userManager->get($share->getUserId())->getDisplayName(),
201
				'language' => $this->config->getUserValue(
202
					$share->getUserId(),
203
					'core', 'lang'
204
				),
205
				'link' => $this->urlGenerator->getAbsoluteURL(
206
					$this->urlGenerator->linkToRoute(
207
						'polls.page.indexvote',
208
						array('id' => $share->getPollId())
209
					)
210
				)
211
			);
212
213
		} elseif ($share->getType() === 'email') {
214
			$recipients[] = array(
215
				'userId' => $share->getUserEmail(),
216
				'eMailAddress' => $share->getUserEmail(),
217
				'displayName' => $share->getUserEmail(),
218
				'language' => $defaultLang,
219
				'link' => $this->urlGenerator->getAbsoluteURL(
220
					$this->urlGenerator->linkToRoute(
221
						'polls.page.vote_publicpublic',
222
						array('token' => $share->getToken())
223
					)
224
				)
225
			);
226
227
		} elseif ($share->getType() === 'contact') {
228
			$contacts = $contactsManager->search($share->getUserId(), array('FN'));
229
			if (is_array($contacts)) {
230
				$contact = $contacts[0];
231
232
				$recipients[] = array(
233
					'userId' => $share->getUserId(),
234
					'eMailAddress' => $contact['EMAIL'][0],
235
					'displayName' => $contact['FN'],
236
					'language' => $defaultLang,
237
					'link' => $this->urlGenerator->getAbsoluteURL(
238
						$this->urlGenerator->linkToRoute(
239
							'polls.page.vote_publicpublic',
240
							array('token' => $share->getToken())
241
						)
242
					)
243
				);
244
			} else {
245
				return;
246
			}
247
248
		} elseif ($share->getType() === 'external') {
249
			$recipients[] = array(
250
				'userId' => $share->getUserId(),
251
				'eMailAddress' => $share->getUserEmail(),
252
				'displayName' => $share->getUserId(),
253
				'language' => $defaultLang,
254
				'link' => $this->urlGenerator->getAbsoluteURL(
255
					$this->urlGenerator->linkToRoute(
256
						'polls.page.vote_publicpublic',
257
						array('token' => $share->getToken())
258
					)
259
				)
260
			);
261
262
		} elseif ($share->getType() === 'group') {
263
264
			$groupMembers = array_keys($this->groupManager->displayNamesInGroup($share->getUserId()));
265
266
			foreach ($groupMembers as $member) {
267
				if ($skipUser === $member || !$this->userManager->get($member)->isEnabled() ) {
268
					continue;
269
				}
270
271
				$recipients[] = array(
272
					'userId' => $member,
273
					'eMailAddress' => \OC::$server->getConfig()->getUserValue($member, 'settings', 'email'),
274
					'displayName' => $this->userManager->get($member)->getDisplayName(),
275
					'language' => $this->config->getUserValue($member, 'core', 'lang'),
276
					'link' => $this->urlGenerator->getAbsoluteURL(
277
						$this->urlGenerator->linkToRoute(
278
							'polls.page.indexvote', ['id' => $share->getPollId()]
279
						)
280
					)
281
				);
282
283
			}
284
		}
285
		return $recipients;
286
	}
287
288
	/**
289
	 * @param string $token
290
	 */
291
	public function sendInvitationMail($token) {
292
293
		$share = $this->shareMapper->findByToken($token);
294
		$poll = $this->pollMapper->find($share->getPollId());
295
		$owner = $this->userManager->get($poll->getOwner());
296
		$sentMails = [];
297
		$abortedMails = [];
298
299
		$recipients = $this->getRecipientsByShare(
300
			$this->shareMapper->findByToken($token),
301
			$this->config->getUserValue($poll->getOwner(), 'core', 'lang'),
302
			$poll->getOwner()
303
		);
304
305
		foreach ($recipients as $recipient) {
306
			$trans = $this->transFactory->get('polls', $recipient['language']);
307
308
309
			$emailTemplate = $this->mailer->createEMailTemplate('polls.Invitation', [
310
				'owner' => $owner->getDisplayName(),
311
				'title' => $poll->getTitle(),
312
				'link' => $recipient['link']
313
			]);
314
315
			$emailTemplate->setSubject($trans->t('Poll invitation "%s"', $poll->getTitle()));
316
			$emailTemplate->addHeader();
317
			$emailTemplate->addHeading($trans->t('Poll invitation "%s"', $poll->getTitle()), false);
318
319
			$emailTemplate->addBodyText(str_replace(
320
				['{owner}', '{title}'],
321
				[$owner->getDisplayName(), $poll->getTitle()],
322
				$trans->t('{owner} invited you to take part in the poll "{title}"')
323
			));
324
325
			$emailTemplate->addBodyText($poll->getDescription());
326
327
			$emailTemplate->addBodyButton(
328
				htmlspecialchars($trans->t('Go to poll')),
329
				$recipient['link']
330
			);
331
332
			$emailTemplate->addBodyText($trans->t('This link gives you personal access to the poll named above. Press the button above or copy the following link and add it in your browser\'s location bar: '));
333
			$emailTemplate->addBodyText($recipient['link']);
334
335
			$emailTemplate->addFooter($trans->t('This email is sent to you, because you are invited to vote in this poll by the poll owner. At least your name or your email address is recorded in this poll. If you want to get removed from this poll, contact the site administrator or the initiator of this poll, where the mail is sent from.'));
336
337
			try {
338
				$this->sendMail(
339
					$emailTemplate,
340
					$recipient['userId'],
341
					$recipient['eMailAddress'],
342
					$recipient['displayName']
343
				);
344
				$share->setInvitationSent(time());
345
				$this->shareMapper->update($share);
346
				$sentMails[] = $recipient;
347
			} catch (Exception $e) {
348
				$abortedMails[] = $recipient;
349
				\OC::$server->getLogger()->alert('Error sending Mail to ' . json_encode($recipient));
350
			}
351
		}
352
		return ['sentMails' => $sentMails, 'abortedMails' => $abortedMails];
353
	}
354
355
	public function sendNotifications() {
356
		$subscriptions = [];
357
		$log = $this->logMapper->findUnprocessedPolls();
358
359
		foreach ($log as $logItem) {
360
			$subscriptions = array_merge($subscriptions, $this->subscriptionMapper->findAllByPoll($logItem->getPollId()));
361
		}
362
363
		$log = $this->logMapper->findUnprocessed();
364
365
		foreach ($subscriptions as $subscription) {
366
367
			if ($this->userManager->get($subscription->getUserId()) instanceof IUser) {
368
				$lang = $this->config->getUserValue($subscription->getUserId(), 'core', 'lang');
369
			} else {
370
				$lang = $this->config->getUserValue($poll->getOwner(), 'core', 'lang');
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
Comprehensibility Best Practice introduced by
The variable $poll does not seem to be defined for all execution paths leading up to this point.
Loading history...
371
				continue;
372
			}
373
374
			$poll = $this->pollMapper->find($subscription->getPollId());
375
			$trans = $this->transFactory->get('polls', $lang);
376
377
			$url = $this->urlGenerator->getAbsoluteURL(
378
				$this->urlGenerator->linkToRoute(
379
					'polls.page.indexvote',
380
					array('id' => $subscription->getPollId())
381
				)
382
			);
383
384
			$emailTemplate = $this->mailer->createEMailTemplate('polls.Invitation', [
385
				'title' => $poll->getTitle(),
386
				'link' => $url
387
			]);
388
			$emailTemplate->setSubject($trans->t('Polls App - New Activity'));
389
			$emailTemplate->addHeader();
390
			$emailTemplate->addHeading($trans->t('Polls App - New Activity'), false);
391
			$emailTemplate->addBodyText(str_replace(
392
				['{title}'],
393
				[$poll->getTitle()],
394
				$trans->t('"{title}" had recent activity: ')
395
			));
396
397
			foreach ($log as $logItem) {
398
				if ($logItem->getPollId() === $subscription->getPollId()) {
399
					if ($poll->getAnonymous() || $poll->getShowResults() !== "always") {
400
						$displayUser = "A user";
401
					} elseif ($this->userManager->get($logItem->getUserId()) instanceof IUser) {
402
						$displayUser = $this->userManager->get($logItem->getUserId())->getDisplayName();
403
					} else {
404
						$displayUser = $logItem->getUserId();
405
					}
406
407
					if ($logItem->getMessage()) {
408
						$emailTemplate->addBodyText($logItem->getMessage());
409
410
					} elseif ($logItem->getMessageId() === 'setVote') {
411
						$emailTemplate->addBodyText($trans->t(
412
							'- %s voted.',
413
							array($displayUser)
414
						));
415
416
					} elseif ($logItem->getMessageId() === 'updatePoll') {
417
						$emailTemplate->addBodyText($trans->t(
418
							'- %s updated the poll configuration. Please check your votes.',
419
							array($displayUser)
420
						));
421
422
					} elseif ($logItem->getMessageId() === 'deletePoll') {
423
						$emailTemplate->addBodyText($trans->t(
424
							'- %s deleted the poll.',
425
							array($displayUser)
426
						));
427
428
					} elseif ($logItem->getMessageId() === 'restorePoll') {
429
						$emailTemplate->addBodyText($trans->t(
430
							'- %s restored the poll.',
431
							array($displayUser)
432
						));
433
434
					} elseif ($logItem->getMessageId() === 'expirePoll') {
435
						$emailTemplate->addBodyText($trans->t(
436
							'- The poll expired.',
437
							array($displayUser)
438
						));
439
440
					} elseif ($logItem->getMessageId() === 'addOption') {
441
						$emailTemplate->addBodyText($trans->t(
442
							'- %s added a vote option.',
443
							array($displayUser)
444
						));
445
446
					} elseif ($logItem->getMessageId() === 'deleteOption') {
447
						$emailTemplate->addBodyText($trans->t(
448
							'- %s removed a vote option.',
449
							array($displayUser)
450
						));
451
452
					} else {
453
						$emailTemplate->addBodyText(
454
							$logItem->getMessageId() . " (" . $displayUser . ")"
455
						);
456
					}
457
				}
458
459
				$logItem->setProcessed(time());
460
				$this->logMapper->update($logItem);
461
			}
462
463
			$emailTemplate->addBodyButton(
464
				htmlspecialchars($trans->t('Go to poll')),
465
				$url,
466
				/** @scrutinizer ignore-type */ false
467
			);
468
			$emailTemplate->addFooter($trans->t('This email is sent to you, because you subscribed to notifications of this poll. To opt out, visit the poll and remove your subscription.'));
469
470
			try {
471
				$this->sendMail($emailTemplate, $subscription->getUserId());
472
			} catch (Exception $e) {
473
				\OC::$server->getLogger()->alert('Error sending Mail to ' . $subscription->getUserId());
474
			}
475
		}
476
	}
477
}
478