Passed
Pull Request — master (#1234)
by René
04:40
created

MailService::sendInvitation()   A

Complexity

Conditions 4
Paths 7

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 20
c 0
b 0
f 0
dl 0
loc 30
ccs 0
cts 14
cp 0
rs 9.6
cc 4
nc 7
nop 1
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 OCP\IUser;
27
use OCP\IUserManager;
28
use OCP\IGroupManager;
29
use OCP\IConfig;
30
use OCP\IURLGenerator;
31
use OCP\IL10N;
32
use OCP\L10N\IFactory;
33
use OCP\Mail\IMailer;
34
use OCP\Mail\IEMailTemplate;
35
36
use OCA\Polls\Db\SubscriptionMapper;
37
use OCA\Polls\Db\PollMapper;
38
use OCA\Polls\Db\ShareMapper;
39
use OCA\Polls\Db\Share;
40
use OCA\Polls\Db\LogMapper;
41
use OCA\Polls\Db\Log;
42
use OCA\Polls\Model\Contact;
43
use OCA\Polls\Model\Email;
44
use OCA\Polls\Model\Group;
45
use OCA\Polls\Model\User;
46
47
class MailService {
48
49
	/** @var IUserManager */
50
	private $userManager;
51
52
	/** @var IGroupManager */
53
	private $groupManager;
54
55
	/** @var IConfig */
56
	private $config;
57
58
	/** @var IURLGenerator */
59
	private $urlGenerator;
60
61
	/** @var IL10N */
62
	private $trans;
63
64
	/** @var IFactory */
65
	private $transFactory;
66
67
	/** @var IMailer */
68
	private $mailer;
69
70
	/** @var SubscriptionMapper */
71
	private $subscriptionMapper;
72
73
	/** @var ShareMapper */
74
	private $shareMapper;
75
76
	/** @var PollMapper */
77
	private $pollMapper;
78
79
	/** @var LogMapper */
80
	private $logMapper;
81
82
	/**
83
	 * MailService constructor.
84
	 * @param IUserManager $userManager
85
	 * @param IGroupManager $groupManager
86
	 * @param IConfig $config
87
	 * @param IURLGenerator $urlGenerator
88
	 * @param IL10N $trans
89
	 * @param IFactory $transFactory
90
	 * @param IMailer $mailer
91
	 * @param SubscriptionMapper $subscriptionMapper
92
	 * @param ShareMapper $shareMapper
93
	 * @param PollMapper $pollMapper
94
	 * @param LogMapper $logMapper
95
	 */
96
97
	public function __construct(
98
		IUserManager $userManager,
99
		IGroupManager $groupManager,
100
		IConfig $config,
101
		IURLGenerator $urlGenerator,
102
		IL10N $trans,
103
		IFactory $transFactory,
104
		IMailer $mailer,
105
		ShareMapper $shareMapper,
106
		SubscriptionMapper $subscriptionMapper,
107
		PollMapper $pollMapper,
108
		LogMapper $logMapper
109
	) {
110
		$this->config = $config;
111
		$this->userManager = $userManager;
112
		$this->groupManager = $groupManager;
113
		$this->urlGenerator = $urlGenerator;
114
		$this->trans = $trans;
115
		$this->transFactory = $transFactory;
116
		$this->mailer = $mailer;
117
		$this->shareMapper = $shareMapper;
118
		$this->subscriptionMapper = $subscriptionMapper;
119
		$this->pollMapper = $pollMapper;
120
		$this->logMapper = $logMapper;
121
	}
122
123
124
	/**
125
	 * sendMail - Send eMail and evaluate recipient's mail address
126
	 * and displayname if $userId is a site user
127
	 * @param IEmailTemplate $emailTemplate
128
	 * @param String $userId
129
	 * @param String $emailAddress, ignored, when $userId is set
130
	 * @param String $displayName, ignored, when $userId is set
131
	 * @return String
132
	 */
133
134
	private function sendMail($emailTemplate, $emailAddress, $displayName) {
135
		if (!$emailAddress || !filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
136
			throw new \Exception('Invalid email address (' . $emailAddress . ')');
137
		}
138
139
		try {
140
			$message = $this->mailer->createMessage();
141
			$message->setTo([$emailAddress => $displayName]);
142
			$message->useTemplate($emailTemplate);
143
			$this->mailer->send($message);
144
145
			return null;
146
		} catch (\Exception $e) {
147
			\OC::$server->getLogger()->logException($e->getMessage(), ['app' => 'polls']);
148
			throw $e;
149
		}
150
	}
151
152
	/**
153
	 * @param string $token
154
	 */
155
	public function sendInvitation($token) {
156
		$share = $this->shareMapper->findByToken($token);
157
		$poll = $this->pollMapper->find($share->getPollId());
158
		$sentMails = [];
159
		$abortedMails = [];
160
161
		foreach ($share->getMembers() as $recipient) {
162
			//skip poll owner
163
			if ($recipient->getId() === $poll->getOwner()) {
164
				continue;
165
			}
166
167
			$emailTemplate = $this->generateInvitation($recipient, $poll, $share->getURL());
168
169
			try {
170
				$this->sendMail(
171
					$emailTemplate,
172
					$recipient->getEmailAddress(),
173
					$recipient->getDisplayName()
174
				);
175
				$share->setInvitationSent(time());
176
				$this->shareMapper->update($share);
177
				$sentMails[] = $recipient->getId();
178
			} catch (\Exception $e) {
179
				$abortedMails[] = $recipient->getId();
180
				\OC::$server->getLogger()->alert('Error sending Mail to ' . json_encode($recipient));
181
			}
182
183
		}
184
		return ['sentMails' => $sentMails, 'abortedMails' => $abortedMails];
185
	}
186
187
	public function sendNotifications() {
188
		$subscriptions = [];
189
		$log = $this->logMapper->findUnprocessedPolls();
190
191
		foreach ($log as $logItem) {
192
			$subscriptions = array_merge($subscriptions, $this->subscriptionMapper->findAllByPoll($logItem->getPollId()));
193
		}
194
195
		$log = $this->logMapper->findUnprocessed();
196
197
		foreach ($subscriptions as $subscription) {
198
			$poll = $this->pollMapper->find($subscription->getPollId());
199
200
			if ($this->userManager->get($subscription->getUserId()) instanceof IUser) {
201
				$recipient = new User($subscription->getUserId());
202
				$url = $this->urlGenerator->linkToRouteAbsolute(
203
					'polls.page.vote',
204
					['id' => $subscription->getPollId()]
205
				);
206
			} else {
207
				try {
208
					$share = $this->shareMapper->findByPollAndUser($subscription->getPollId(), $subscription->getUserId());
209
					$recipient = $share->getUserObject();
210
					$url = $share->getURL();
211
				} catch (\Exception $e) {
212
					continue;
213
				}
214
			}
215
216
			$emailTemplate = $this->generateNotification($recipient, $poll, $url, $log);
217
218
			try {
219
				$this->sendMail(
220
					$emailTemplate,
221
					$recipient->getEmailAddress(),
222
					$recipient->getDisplayName()
223
				);
224
			} catch (\Exception $e) {
225
				\OC::$server->getLogger()->alert('Error sending Mail to ' . $recipient->getId());
226
			}
227
		}
228
	}
229
230
	/**
231
	 * generateNotification
232
	 * @param UserGroupClass $recipient
0 ignored issues
show
Bug introduced by
The type OCA\Polls\Service\UserGroupClass was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
233
	 * @param Poll $poll
234
	 * @return Object $emailTemplate
235
	 */
236
237
	private function generateNotification($recipient, $poll, $url, $log) {
238
		$owner = $poll->getOwnerUserObject();
239
		if ($recipient->getLanguage()) {
240
			$trans = $this->transFactory->get('polls', $recipient->getLanguage());
241
		} else {
242
			$trans = $this->transFactory->get('polls', $owner->getLanguage());
243
		}
244
		$emailTemplate = $this->mailer->createEMailTemplate('polls.Notification', [
245
			'title' => $poll->getTitle(),
246
			'link' => $url
247
		]);
248
249
		$emailTemplate->setSubject($trans->t('Polls App - New Activity'));
250
		$emailTemplate->addHeader();
251
		$emailTemplate->addHeading($trans->t('Polls App - New Activity'), false);
252
		$emailTemplate->addBodyText(str_replace(
253
			['{title}'],
254
			[$poll->getTitle()],
255
			$trans->t('"{title}" had recent activity: ')
256
		));
257
		foreach ($log as $logItem) {
258
259
			if ($logItem->getPollId() === $poll->getId()) {
260
				if ($poll->getAnonymous() || $poll->getShowResults() !== "always") {
261
					$displayUser = $trans->t('A user');
262
				} elseif ($this->userManager->get($logItem->getUserId()) instanceof IUser) {
263
						$actor = new User($subscription->getUserId());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $subscription seems to be never defined.
Loading history...
264
						$displayUser = $actor->getDisplayName();
265
				} else {
266
					try {
267
						$share = $this->shareMapper->findByPollAndUser($subscription->getPollId(), $logItem->getUserId());
268
						$displayUser = $share->getUserObject()->getDisplayName();
269
					} catch (\Exception $e) {
270
						$displayUser = $logItem->getUserId();
271
					}
272
				}
273
274
				if ($logItem->getMessage()) {
275
					$emailTemplate->addBodyText($logItem->getMessage());
276
				} elseif ($logItem->getMessageId() === Log::MSG_ID_SETVOTE) {
277
					$emailTemplate->addBodyText($trans->t(
278
						'- %s voted.',
279
						[$displayUser]
280
					));
281
				} elseif ($logItem->getMessageId() === Log::MSG_ID_UPDATEPOLL) {
282
					$emailTemplate->addBodyText($trans->t(
283
						'- Updated poll configuration. Please check your votes.',
284
						[$displayUser]
285
					));
286
				} elseif ($logItem->getMessageId() === Log::MSG_ID_DELETEPOLL) {
287
					$emailTemplate->addBodyText($trans->t(
288
						'- The poll got deleted.',
289
						[$displayUser]
290
					));
291
				} elseif ($logItem->getMessageId() === Log::MSG_ID_RESTOREPOLL) {
292
					$emailTemplate->addBodyText($trans->t(
293
						'- The poll got restored.',
294
						[$displayUser]
295
					));
296
				} elseif ($logItem->getMessageId() === Log::MSG_ID_EXPIREPOLL) {
297
					$emailTemplate->addBodyText($trans->t(
298
						'- The poll closed.',
299
						[$displayUser]
300
					));
301
				} elseif ($logItem->getMessageId() === Log::MSG_ID_ADDOPTION) {
302
					$emailTemplate->addBodyText($trans->t(
303
						'- A vote option was added.',
304
						[$displayUser]
305
					));
306
				} elseif ($logItem->getMessageId() === Log::MSG_ID_DELETEOPTION) {
307
					$emailTemplate->addBodyText($trans->t(
308
						'- A vote option was removed.',
309
						[$displayUser]
310
					));
311
				} else {
312
					$emailTemplate->addBodyText(
313
						$logItem->getMessageId() . " (" . $displayUser . ")"
314
					);
315
				}
316
			}
317
318
			$logItem->setProcessed(time());
319
			$this->logMapper->update($logItem);
320
		}
321
322
		$emailTemplate->addBodyButton(
323
			htmlspecialchars($trans->t('Go to poll')),
324
			$url,
325
			/** @scrutinizer ignore-type */ false
326
		);
327
		$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.'));
328
329
		return $emailTemplate;
330
	}
331
332
		/**
333
		 * generateInvitation
334
		 * @param UserGroupClass $recipient
335
		 * @param Poll $poll
336
		 * @return Object $emailTemplate
337
		 */
338
339
		private function generateInvitation($recipient, $poll, $url) {
340
			$owner = $poll->getOwnerUserObject();
341
			if ($recipient->getLanguage()) {
342
				$trans = $this->transFactory->get('polls', $recipient->getLanguage());
343
			} else {
344
				$trans = $this->transFactory->get('polls', $owner->getLanguage());
345
			}
346
347
			$emailTemplate = $this->mailer->createEMailTemplate('polls.Invitation', [
348
				'owner' => $owner->getDisplayName(),
349
				'title' => $poll->getTitle(),
350
				'link' => $url
351
			]);
352
353
			$emailTemplate->setSubject($trans->t('Poll invitation "%s"', $poll->getTitle()));
354
			$emailTemplate->addHeader();
355
			$emailTemplate->addHeading($trans->t('Poll invitation "%s"', $poll->getTitle()), false);
356
			$emailTemplate->addBodyText(str_replace(
357
				['{owner}', '{title}'],
358
				[$owner->getDisplayName(), $poll->getTitle()],
359
				$trans->t('{owner} invited you to take part in the poll "{title}"')
360
			));
361
			$emailTemplate->addBodyText($poll->getDescription());
362
			$emailTemplate->addBodyButton(
363
				htmlspecialchars($trans->t('Go to poll')),
364
				$url
365
			);
366
			$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: '));
367
			$emailTemplate->addBodyText($url);
368
			$emailTemplate->addBodyText($trans->t('Do not share this link with other people, because it is connected to your votes.'));
369
			$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.'));
370
371
			return $emailTemplate;
372
		}
373
374
}
375