Completed
Push — master ( ae2e92...420fd3 )
by Thomas
35:58 queued 24:50
created

MailNotifications::createMailBody()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
nc 8
nop 5
dl 0
loc 25
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Lukas Reschke <[email protected]>
6
 * @author Morris Jobke <[email protected]>
7
 * @author Robin McCorkell <[email protected]>
8
 * @author Roeland Jago Douma <[email protected]>
9
 * @author scolebrook <[email protected]>
10
 * @author Thomas Müller <[email protected]>
11
 * @author Vincent Petry <[email protected]>
12
 *
13
 * @copyright Copyright (c) 2018, ownCloud GmbH
14
 * @license AGPL-3.0
15
 *
16
 * This code is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License, version 3,
18
 * as published by the Free Software Foundation.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License, version 3,
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
27
 *
28
 */
29
30
namespace OC\Share;
31
32
use DateTime;
33
use OCP\IL10N;
34
use OCP\IURLGenerator;
35
use OCP\IUser;
36
use OCP\Mail\IMailer;
37
use OCP\ILogger;
38
use OCP\Defaults;
39
use OCP\Util;
40
41
/**
42
 * Class MailNotifications
43
 *
44
 * @package OC\Share
45
 */
46
class MailNotifications {
47
48
	/** @var IUser sender userId */
49
	private $user;
50
	/** @var string sender email address */
51
	private $replyTo;
52
	/** @var string */
53
	private $senderDisplayName;
54
	/** @var IL10N */
55
	private $l;
56
	/** @var IMailer */
57
	private $mailer;
58
	/** @var Defaults */
59
	private $defaults;
60
	/** @var ILogger */
61
	private $logger;
62
	/** @var IURLGenerator */
63
	private $urlGenerator;
64
65
	/**
66
	 * @param IUser $user
67
	 * @param IL10N $l10n
68
	 * @param IMailer $mailer
69
	 * @param ILogger $logger
70
	 * @param Defaults $defaults
71
	 * @param IURLGenerator $urlGenerator
72
	 */
73
	public function __construct(IUser $user,
74
								IL10N $l10n,
75
								IMailer $mailer,
76
								ILogger $logger,
77
								Defaults $defaults,
78
								IURLGenerator $urlGenerator) {
79
		$this->l = $l10n;
80
		$this->user = $user;
81
		$this->mailer = $mailer;
82
		$this->logger = $logger;
83
		$this->defaults = $defaults;
84
		$this->urlGenerator = $urlGenerator;
85
86
		$this->replyTo = $this->user->getEMailAddress();
87
		$this->senderDisplayName = $this->user->getDisplayName();
88
	}
89
90
	/**
91
	 * split a list of comma or semicolon separated email addresses
92
	 *
93
	 * @param string $mailsstring email addresses
94
	 * @return array list of individual addresses
95
	 */
96
	private function _mailStringToArray($mailsstring) {
97
		$sanatised  = str_replace([', ', '; ', ',', ';', ' '], ',', $mailsstring);
98
		$mail_array = explode(',', $sanatised);
99
100
		return $mail_array;
101
	}
102
103
	/**
104
	 * inform users if a file was shared with them
105
	 *
106
	 * @param IUser[] $recipientList list of recipients
107
	 * @param string $itemSource shared item source
108
	 * @param string $itemType shared item type
109
	 * @return array list of user to whom the mail send operation failed
110
	 */
111
	public function sendInternalShareMail($recipientList, $itemSource, $itemType) {
112
		$noMail = [];
113
114
		foreach ($recipientList as $recipient) {
115
			$recipientDisplayName = $recipient->getDisplayName();
116
			$to = $recipient->getEMailAddress();
117
118
			if ($to === null || $to === '') {
119
				$noMail[] = $recipientDisplayName;
120
				continue;
121
			}
122
123
			$items = $this->getItemSharedWithUser($itemSource, $itemType, $recipient);
124
			$filename = trim($items[0]['file_target'], '/');
125
			$subject = (string) $this->l->t('%s shared »%s« with you', [$this->senderDisplayName, $filename]);
126
			$expiration = null;
127
			if (isset($items[0]['expiration'])) {
128
				try {
129
					$date = new DateTime($items[0]['expiration']);
130
					$expiration = $date->getTimestamp();
131
				} catch (\Exception $e) {
132
					$this->logger->error("Couldn't read date: ".$e->getMessage(), ['app' => 'sharing']);
133
				}
134
			}
135
136
			$link = $this->urlGenerator->linkToRouteAbsolute(
137
				'files.viewcontroller.showFile',
138
				['fileId' => $items[0]['item_source']]
139
			);
140
141
			list($htmlBody, $textBody) = $this->createMailBody($filename, $link, $expiration, null, 'internal');
142
143
			// send it out now
144
			try {
145
				$message = $this->mailer->createMessage();
146
				$message->setSubject($subject);
147
				$message->setTo([$to => $recipientDisplayName]);
148
				$message->setHtmlBody($htmlBody);
0 ignored issues
show
Bug introduced by
It seems like $htmlBody defined by $this->createMailBody($f...tion, null, 'internal') on line 141 can also be of type boolean; however, OC\Mail\Message::setHtmlBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
149
				$message->setPlainBody($textBody);
0 ignored issues
show
Bug introduced by
It seems like $textBody defined by $this->createMailBody($f...tion, null, 'internal') on line 141 can also be of type boolean; however, OC\Mail\Message::setPlainBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
150
				$message->setFrom([
151
					Util::getDefaultEmailAddress('sharing-noreply') =>
152
						(string)$this->l->t('%s via %s', [
153
							$this->senderDisplayName,
154
							$this->defaults->getName()
155
						]),
156
					]);
157
				if(!is_null($this->replyTo)) {
158
					$message->setReplyTo([$this->replyTo]);
159
				}
160
161
				$this->mailer->send($message);
162
			} catch (\Exception $e) {
163
				$this->logger->error("Can't send mail to inform the user about an internal share: ".$e->getMessage(), ['app' => 'sharing']);
164
				$noMail[] = $recipientDisplayName;
165
			}
166
		}
167
168
		return $noMail;
169
170
	}
171
172
	public function sendLinkShareMail($recipient, $filename, $link, $expiration, $personalNote = null) {
173
		$subject = (string)$this->l->t('%s shared »%s« with you', [$this->senderDisplayName, $filename]);
174
		list($htmlBody, $textBody) = $this->createMailBody($filename, $link, $expiration, $personalNote);
175
176
		return $this->sendLinkShareMailFromBody($recipient, $subject, $htmlBody, $textBody);
177
	}
178
179
	/**
180
	 * inform recipient about public link share
181
	 *
182
	 * @param string $recipient recipient email address
183
	 * @param string $filename the shared file
0 ignored issues
show
Bug introduced by
There is no parameter named $filename. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
184
	 * @param string $link the public link
0 ignored issues
show
Bug introduced by
There is no parameter named $link. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
185
	 * @param array $options allows ['cc'] and ['bcc'] recipients
186
	 * @param int $expiration expiration date (timestamp)
0 ignored issues
show
Bug introduced by
There is no parameter named $expiration. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
187
	 * @return string[] $result of failed recipients
188
	 */
189
	public function sendLinkShareMailFromBody($recipient, $subject, $htmlBody, $textBody, $options = array()) {
190
191
		$recipients    = $this->_mailStringToArray($recipient);
192
		$ccRecipients  = (isset($options['cc']) && $options['cc'] !== '') ? $this->_mailStringToArray($options['cc']) : null;
193
		$bccRecipients = (isset($options['bcc']) && $options['bcc'] !== '') ? $this->_mailStringToArray($options['bcc']) : null;
194
195
		try {
196
			$message = $this->mailer->createMessage();
197
			$message->setSubject($subject);
198
			$message->setTo($recipients);
199
			if ($htmlBody !== null) {
200
				$message->setHtmlBody($htmlBody);
201
			}
202
			if ($bccRecipients !== null) {
203
				$message->setBcc($bccRecipients);
204
			}
205
			if ($ccRecipients !== null) {
206
				$message->setCc($ccRecipients);
207
			}
208
			$message->setPlainBody($textBody);
209
			$message->setFrom([
210
				Util::getDefaultEmailAddress('sharing-noreply') =>
211
					(string)$this->l->t('%s via %s', [
212
						$this->senderDisplayName,
213
						$this->defaults->getName()
214
					]),
215
			]);
216
			if(!is_null($this->replyTo)) {
217
				$message->setReplyTo([$this->replyTo]);
218
			}
219
220
			return $this->mailer->send($message);
221
		} catch (\Exception $e) {
222
			$this->logger->error("Can't send mail with public link to $recipient: ".$e->getMessage(), ['app' => 'sharing']);
223
			return [$recipient];
224
		}
225
	}
226
227
	/**
228
	 * create mail body for plain text and html mail
229
	 *
230
	 * @param string $filename the shared file
231
	 * @param string $link link to the shared file
232
	 * @param int $expiration expiration date (timestamp)
233
	 * @param string $personalNote optional personal note
234
	 * @param string $prefix prefix of mail template files
235
	 * @return array an array of the html mail body and the plain text mail body
236
	 */
237
	public function createMailBody($filename, $link, $expiration, $personalNote = null, $prefix = '') {
238
		$formattedDate = $expiration ? $this->l->l('date', $expiration) : null;
239
240
		$html = new \OC_Template('core', $prefix . 'mail', '');
241
		$html->assign('link', $link);
242
		$html->assign('user_displayname', $this->senderDisplayName);
243
		$html->assign('filename', $filename);
244
		$html->assign('expiration',  $formattedDate);
245
		if ($personalNote !== null && $personalNote !== '') {
246
			$html->assign('personal_note', $personalNote);
247
		}
248
		$htmlMail = $html->fetchPage();
249
250
		$plainText = new \OC_Template('core', $prefix . 'altmail', '');
251
		$plainText->assign('link', $link);
252
		$plainText->assign('user_displayname', $this->senderDisplayName);
253
		$plainText->assign('filename', $filename);
254
		$plainText->assign('expiration', $formattedDate);
255
		if ($personalNote !== null && $personalNote !== '') {
256
			$plainText->assign('personal_note', $personalNote);
257
		}
258
		$plainTextMail = $plainText->fetchPage();
259
260
		return [$htmlMail, $plainTextMail];
261
	}
262
263
	/**
264
	 * @param string $itemSource
265
	 * @param string $itemType
266
	 * @param IUser $recipient
267
	 * @return array
268
	 */
269
	protected function getItemSharedWithUser($itemSource, $itemType, $recipient) {
270
		return Share::getItemSharedWithUser($itemType, $itemSource, $recipient->getUID());
271
	}
272
273
}
274