Passed
Push — master ( fc4e87...bbd3e2 )
by Blizzz
17:23 queued 18s
created
apps/dav/lib/CalDAV/Schedule/IMipPlugin.php 2 patches
Indentation   +619 added lines, -619 removed lines patch added patch discarded remove patch
@@ -71,176 +71,176 @@  discard block
 block discarded – undo
71 71
  * @license http://sabre.io/license/ Modified BSD License
72 72
  */
73 73
 class IMipPlugin extends SabreIMipPlugin {
74
-	/** @var string */
75
-	private $userId;
76
-
77
-	/** @var IConfig */
78
-	private $config;
79
-
80
-	/** @var IMailer */
81
-	private $mailer;
82
-
83
-	private LoggerInterface $logger;
84
-
85
-	/** @var ITimeFactory */
86
-	private $timeFactory;
87
-
88
-	/** @var L10NFactory */
89
-	private $l10nFactory;
90
-
91
-	/** @var IURLGenerator */
92
-	private $urlGenerator;
93
-
94
-	/** @var ISecureRandom */
95
-	private $random;
96
-
97
-	/** @var IDBConnection */
98
-	private $db;
99
-
100
-	/** @var Defaults */
101
-	private $defaults;
102
-
103
-	/** @var IUserManager */
104
-	private $userManager;
105
-
106
-	public const MAX_DATE = '2038-01-01';
107
-
108
-	public const METHOD_REQUEST = 'request';
109
-	public const METHOD_REPLY = 'reply';
110
-	public const METHOD_CANCEL = 'cancel';
111
-	public const IMIP_INDENT = 15; // Enough for the length of all body bullet items, in all languages
112
-
113
-	public function __construct(IConfig $config, IMailer $mailer,
114
-								LoggerInterface $logger,
115
-								ITimeFactory $timeFactory, L10NFactory $l10nFactory,
116
-								IURLGenerator $urlGenerator, Defaults $defaults,
117
-								ISecureRandom $random, IDBConnection $db, IUserManager $userManager,
118
-								$userId) {
119
-		parent::__construct('');
120
-		$this->userId = $userId;
121
-		$this->config = $config;
122
-		$this->mailer = $mailer;
123
-		$this->logger = $logger;
124
-		$this->timeFactory = $timeFactory;
125
-		$this->l10nFactory = $l10nFactory;
126
-		$this->urlGenerator = $urlGenerator;
127
-		$this->random = $random;
128
-		$this->db = $db;
129
-		$this->defaults = $defaults;
130
-		$this->userManager = $userManager;
131
-	}
132
-
133
-	/**
134
-	 * Event handler for the 'schedule' event.
135
-	 *
136
-	 * @param Message $iTipMessage
137
-	 * @return void
138
-	 */
139
-	public function schedule(Message $iTipMessage) {
140
-		// Not sending any emails if the system considers the update
141
-		// insignificant.
142
-		if (!$iTipMessage->significantChange) {
143
-			if (!$iTipMessage->scheduleStatus) {
144
-				$iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
145
-			}
146
-			return;
147
-		}
148
-
149
-		$summary = $iTipMessage->message->VEVENT->SUMMARY;
150
-
151
-		if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') {
152
-			return;
153
-		}
154
-
155
-		if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') {
156
-			return;
157
-		}
158
-
159
-		// don't send out mails for events that already took place
160
-		$lastOccurrence = $this->getLastOccurrence($iTipMessage->message);
161
-		$currentTime = $this->timeFactory->getTime();
162
-		if ($lastOccurrence < $currentTime) {
163
-			return;
164
-		}
165
-
166
-		// Strip off mailto:
167
-		$sender = substr($iTipMessage->sender, 7);
168
-		$recipient = substr($iTipMessage->recipient, 7);
169
-		if (!$this->mailer->validateMailAddress($recipient)) {
170
-			// Nothing to send if the recipient doesn't have a valid email address
171
-			$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
172
-			return;
173
-		}
174
-
175
-		$recipientName = $iTipMessage->recipientName ?: null;
176
-
177
-		/** @var Parameter|string|null $senderName */
178
-		$senderName = $iTipMessage->senderName ?: null;
179
-		if($senderName instanceof Parameter) {
180
-			$senderName = $senderName->getValue() ?? null;
181
-		}
182
-
183
-		if ($senderName === null || empty(trim($senderName))) {
184
-			$senderName = $this->userManager->getDisplayName($this->userId);
185
-		}
186
-
187
-		/** @var VEvent $vevent */
188
-		$vevent = $iTipMessage->message->VEVENT;
189
-
190
-		$attendee = $this->getCurrentAttendee($iTipMessage);
191
-		$defaultLang = $this->l10nFactory->findGenericLanguage();
192
-		$lang = $this->getAttendeeLangOrDefault($defaultLang, $attendee);
193
-		$l10n = $this->l10nFactory->get('dav', $lang);
194
-
195
-		$meetingAttendeeName = $recipientName ?: $recipient;
196
-		$meetingInviteeName = $senderName ?: $sender;
197
-
198
-		$meetingTitle = $vevent->SUMMARY;
199
-		$meetingDescription = $vevent->DESCRIPTION;
200
-
201
-
202
-		$meetingUrl = $vevent->URL;
203
-		$meetingLocation = $vevent->LOCATION;
204
-
205
-		$defaultVal = '--';
206
-
207
-		$method = self::METHOD_REQUEST;
208
-		switch (strtolower($iTipMessage->method)) {
209
-			case self::METHOD_REPLY:
210
-				$method = self::METHOD_REPLY;
211
-				break;
212
-			case self::METHOD_CANCEL:
213
-				$method = self::METHOD_CANCEL;
214
-				break;
215
-		}
216
-
217
-		$data = [
218
-			'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
219
-			'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
220
-			'meeting_title' => (string)$meetingTitle ?: $defaultVal,
221
-			'meeting_description' => (string)$meetingDescription ?: $defaultVal,
222
-			'meeting_url' => (string)$meetingUrl ?: $defaultVal,
223
-		];
224
-
225
-		$fromEMail = Util::getDefaultEmailAddress('invitations-noreply');
226
-		$fromName = $l10n->t('%1$s via %2$s', [$senderName ?? $this->userId, $this->defaults->getName()]);
227
-
228
-		$message = $this->mailer->createMessage()
229
-			->setFrom([$fromEMail => $fromName])
230
-			->setTo([$recipient => $recipientName])
231
-			->setReplyTo([$sender => $senderName]);
232
-
233
-		$template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
234
-		$template->addHeader();
235
-
236
-		$summary = ((string) $summary !== '') ? (string) $summary : $l10n->t('Untitled event');
237
-
238
-		$this->addSubjectAndHeading($template, $l10n, $method, $summary);
239
-		$this->addBulletList($template, $l10n, $vevent);
240
-
241
-		// Only add response buttons to invitation requests: Fix Issue #11230
242
-		if (($method == self::METHOD_REQUEST) && $this->getAttendeeRsvpOrReqForParticipant($attendee)) {
243
-			/*
74
+    /** @var string */
75
+    private $userId;
76
+
77
+    /** @var IConfig */
78
+    private $config;
79
+
80
+    /** @var IMailer */
81
+    private $mailer;
82
+
83
+    private LoggerInterface $logger;
84
+
85
+    /** @var ITimeFactory */
86
+    private $timeFactory;
87
+
88
+    /** @var L10NFactory */
89
+    private $l10nFactory;
90
+
91
+    /** @var IURLGenerator */
92
+    private $urlGenerator;
93
+
94
+    /** @var ISecureRandom */
95
+    private $random;
96
+
97
+    /** @var IDBConnection */
98
+    private $db;
99
+
100
+    /** @var Defaults */
101
+    private $defaults;
102
+
103
+    /** @var IUserManager */
104
+    private $userManager;
105
+
106
+    public const MAX_DATE = '2038-01-01';
107
+
108
+    public const METHOD_REQUEST = 'request';
109
+    public const METHOD_REPLY = 'reply';
110
+    public const METHOD_CANCEL = 'cancel';
111
+    public const IMIP_INDENT = 15; // Enough for the length of all body bullet items, in all languages
112
+
113
+    public function __construct(IConfig $config, IMailer $mailer,
114
+                                LoggerInterface $logger,
115
+                                ITimeFactory $timeFactory, L10NFactory $l10nFactory,
116
+                                IURLGenerator $urlGenerator, Defaults $defaults,
117
+                                ISecureRandom $random, IDBConnection $db, IUserManager $userManager,
118
+                                $userId) {
119
+        parent::__construct('');
120
+        $this->userId = $userId;
121
+        $this->config = $config;
122
+        $this->mailer = $mailer;
123
+        $this->logger = $logger;
124
+        $this->timeFactory = $timeFactory;
125
+        $this->l10nFactory = $l10nFactory;
126
+        $this->urlGenerator = $urlGenerator;
127
+        $this->random = $random;
128
+        $this->db = $db;
129
+        $this->defaults = $defaults;
130
+        $this->userManager = $userManager;
131
+    }
132
+
133
+    /**
134
+     * Event handler for the 'schedule' event.
135
+     *
136
+     * @param Message $iTipMessage
137
+     * @return void
138
+     */
139
+    public function schedule(Message $iTipMessage) {
140
+        // Not sending any emails if the system considers the update
141
+        // insignificant.
142
+        if (!$iTipMessage->significantChange) {
143
+            if (!$iTipMessage->scheduleStatus) {
144
+                $iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
145
+            }
146
+            return;
147
+        }
148
+
149
+        $summary = $iTipMessage->message->VEVENT->SUMMARY;
150
+
151
+        if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto') {
152
+            return;
153
+        }
154
+
155
+        if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto') {
156
+            return;
157
+        }
158
+
159
+        // don't send out mails for events that already took place
160
+        $lastOccurrence = $this->getLastOccurrence($iTipMessage->message);
161
+        $currentTime = $this->timeFactory->getTime();
162
+        if ($lastOccurrence < $currentTime) {
163
+            return;
164
+        }
165
+
166
+        // Strip off mailto:
167
+        $sender = substr($iTipMessage->sender, 7);
168
+        $recipient = substr($iTipMessage->recipient, 7);
169
+        if (!$this->mailer->validateMailAddress($recipient)) {
170
+            // Nothing to send if the recipient doesn't have a valid email address
171
+            $iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
172
+            return;
173
+        }
174
+
175
+        $recipientName = $iTipMessage->recipientName ?: null;
176
+
177
+        /** @var Parameter|string|null $senderName */
178
+        $senderName = $iTipMessage->senderName ?: null;
179
+        if($senderName instanceof Parameter) {
180
+            $senderName = $senderName->getValue() ?? null;
181
+        }
182
+
183
+        if ($senderName === null || empty(trim($senderName))) {
184
+            $senderName = $this->userManager->getDisplayName($this->userId);
185
+        }
186
+
187
+        /** @var VEvent $vevent */
188
+        $vevent = $iTipMessage->message->VEVENT;
189
+
190
+        $attendee = $this->getCurrentAttendee($iTipMessage);
191
+        $defaultLang = $this->l10nFactory->findGenericLanguage();
192
+        $lang = $this->getAttendeeLangOrDefault($defaultLang, $attendee);
193
+        $l10n = $this->l10nFactory->get('dav', $lang);
194
+
195
+        $meetingAttendeeName = $recipientName ?: $recipient;
196
+        $meetingInviteeName = $senderName ?: $sender;
197
+
198
+        $meetingTitle = $vevent->SUMMARY;
199
+        $meetingDescription = $vevent->DESCRIPTION;
200
+
201
+
202
+        $meetingUrl = $vevent->URL;
203
+        $meetingLocation = $vevent->LOCATION;
204
+
205
+        $defaultVal = '--';
206
+
207
+        $method = self::METHOD_REQUEST;
208
+        switch (strtolower($iTipMessage->method)) {
209
+            case self::METHOD_REPLY:
210
+                $method = self::METHOD_REPLY;
211
+                break;
212
+            case self::METHOD_CANCEL:
213
+                $method = self::METHOD_CANCEL;
214
+                break;
215
+        }
216
+
217
+        $data = [
218
+            'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
219
+            'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
220
+            'meeting_title' => (string)$meetingTitle ?: $defaultVal,
221
+            'meeting_description' => (string)$meetingDescription ?: $defaultVal,
222
+            'meeting_url' => (string)$meetingUrl ?: $defaultVal,
223
+        ];
224
+
225
+        $fromEMail = Util::getDefaultEmailAddress('invitations-noreply');
226
+        $fromName = $l10n->t('%1$s via %2$s', [$senderName ?? $this->userId, $this->defaults->getName()]);
227
+
228
+        $message = $this->mailer->createMessage()
229
+            ->setFrom([$fromEMail => $fromName])
230
+            ->setTo([$recipient => $recipientName])
231
+            ->setReplyTo([$sender => $senderName]);
232
+
233
+        $template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
234
+        $template->addHeader();
235
+
236
+        $summary = ((string) $summary !== '') ? (string) $summary : $l10n->t('Untitled event');
237
+
238
+        $this->addSubjectAndHeading($template, $l10n, $method, $summary);
239
+        $this->addBulletList($template, $l10n, $vevent);
240
+
241
+        // Only add response buttons to invitation requests: Fix Issue #11230
242
+        if (($method == self::METHOD_REQUEST) && $this->getAttendeeRsvpOrReqForParticipant($attendee)) {
243
+            /*
244 244
 			** Only offer invitation accept/reject buttons, which link back to the
245 245
 			** nextcloud server, to recipients who can access the nextcloud server via
246 246
 			** their internet/intranet.  Issue #12156
@@ -259,453 +259,453 @@  discard block
 block discarded – undo
259 259
 			** To suppress URLs entirely, set invitation_link_recipients to boolean "no".
260 260
 			*/
261 261
 
262
-			$recipientDomain = substr(strrchr($recipient, "@"), 1);
263
-			$invitationLinkRecipients = explode(',', preg_replace('/\s+/', '', strtolower($this->config->getAppValue('dav', 'invitation_link_recipients', 'yes'))));
264
-
265
-			if (strcmp('yes', $invitationLinkRecipients[0]) === 0
266
-				 || in_array(strtolower($recipient), $invitationLinkRecipients)
267
-				 || in_array(strtolower($recipientDomain), $invitationLinkRecipients)) {
268
-				$this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence);
269
-			}
270
-		}
271
-
272
-		$template->addFooter();
273
-
274
-		$message->useTemplate($template);
275
-
276
-		$attachment = $this->mailer->createAttachment(
277
-			$iTipMessage->message->serialize(),
278
-			'event.ics',// TODO(leon): Make file name unique, e.g. add event id
279
-			'text/calendar; method=' . $iTipMessage->method
280
-		);
281
-		$message->attach($attachment);
282
-
283
-		try {
284
-			$failed = $this->mailer->send($message);
285
-			$iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
286
-			if ($failed) {
287
-				$this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' => implode(', ', $failed)]);
288
-				$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
289
-			}
290
-		} catch (\Exception $ex) {
291
-			$this->logger->error($ex->getMessage(), ['app' => 'dav', 'exception' => $ex]);
292
-			$iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
293
-		}
294
-	}
295
-
296
-	/**
297
-	 * check if event took place in the past already
298
-	 * @param VCalendar $vObject
299
-	 * @return int
300
-	 */
301
-	private function getLastOccurrence(VCalendar $vObject) {
302
-		/** @var VEvent $component */
303
-		$component = $vObject->VEVENT;
304
-
305
-		$firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp();
306
-		// Finding the last occurrence is a bit harder
307
-		if (!isset($component->RRULE)) {
308
-			if (isset($component->DTEND)) {
309
-				$lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp();
310
-			} elseif (isset($component->DURATION)) {
311
-				/** @var \DateTime $endDate */
312
-				$endDate = clone $component->DTSTART->getDateTime();
313
-				// $component->DTEND->getDateTime() returns DateTimeImmutable
314
-				$endDate = $endDate->add(DateTimeParser::parse($component->DURATION->getValue()));
315
-				$lastOccurrence = $endDate->getTimestamp();
316
-			} elseif (!$component->DTSTART->hasTime()) {
317
-				/** @var \DateTime $endDate */
318
-				$endDate = clone $component->DTSTART->getDateTime();
319
-				// $component->DTSTART->getDateTime() returns DateTimeImmutable
320
-				$endDate = $endDate->modify('+1 day');
321
-				$lastOccurrence = $endDate->getTimestamp();
322
-			} else {
323
-				$lastOccurrence = $firstOccurrence;
324
-			}
325
-		} else {
326
-			$it = new EventIterator($vObject, (string)$component->UID);
327
-			$maxDate = new \DateTime(self::MAX_DATE);
328
-			if ($it->isInfinite()) {
329
-				$lastOccurrence = $maxDate->getTimestamp();
330
-			} else {
331
-				$end = $it->getDtEnd();
332
-				while ($it->valid() && $end < $maxDate) {
333
-					$end = $it->getDtEnd();
334
-					$it->next();
335
-				}
336
-				$lastOccurrence = $end->getTimestamp();
337
-			}
338
-		}
339
-
340
-		return $lastOccurrence;
341
-	}
342
-
343
-	/**
344
-	 * @param Message $iTipMessage
345
-	 * @return null|Property
346
-	 */
347
-	private function getCurrentAttendee(Message $iTipMessage) {
348
-		/** @var VEvent $vevent */
349
-		$vevent = $iTipMessage->message->VEVENT;
350
-		$attendees = $vevent->select('ATTENDEE');
351
-		foreach ($attendees as $attendee) {
352
-			/** @var Property $attendee */
353
-			if (strcasecmp($attendee->getValue(), $iTipMessage->recipient) === 0) {
354
-				return $attendee;
355
-			}
356
-		}
357
-		return null;
358
-	}
359
-
360
-	/**
361
-	 * @param string $default
362
-	 * @param Property|null $attendee
363
-	 * @return string
364
-	 */
365
-	private function getAttendeeLangOrDefault($default, Property $attendee = null) {
366
-		if ($attendee !== null) {
367
-			$lang = $attendee->offsetGet('LANGUAGE');
368
-			if ($lang instanceof Parameter) {
369
-				return $lang->getValue();
370
-			}
371
-		}
372
-		return $default;
373
-	}
374
-
375
-	/**
376
-	 * @param Property|null $attendee
377
-	 * @return bool
378
-	 */
379
-	private function getAttendeeRsvpOrReqForParticipant(Property $attendee = null) {
380
-		if ($attendee !== null) {
381
-			$rsvp = $attendee->offsetGet('RSVP');
382
-			if (($rsvp instanceof Parameter) && (strcasecmp($rsvp->getValue(), 'TRUE') === 0)) {
383
-				return true;
384
-			}
385
-			$role = $attendee->offsetGet('ROLE');
386
-			// @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.2.16
387
-			// Attendees without a role are assumed required and should receive an invitation link even if they have no RSVP set
388
-			if ($role === null
389
-				|| (($role instanceof Parameter) && (strcasecmp($role->getValue(), 'REQ-PARTICIPANT') === 0))
390
-				|| (($role instanceof Parameter) && (strcasecmp($role->getValue(), 'OPT-PARTICIPANT') === 0))
391
-			) {
392
-				return true;
393
-			}
394
-		}
395
-		// RFC 5545 3.2.17: default RSVP is false
396
-		return false;
397
-	}
398
-
399
-	/**
400
-	 * @param IL10N $l10n
401
-	 * @param VEvent $vevent
402
-	 */
403
-	private function generateWhenString(IL10N $l10n, VEvent $vevent) {
404
-		$dtstart = $vevent->DTSTART;
405
-		if (isset($vevent->DTEND)) {
406
-			$dtend = $vevent->DTEND;
407
-		} elseif (isset($vevent->DURATION)) {
408
-			$isFloating = $vevent->DTSTART->isFloating();
409
-			$dtend = clone $vevent->DTSTART;
410
-			$endDateTime = $dtend->getDateTime();
411
-			$endDateTime = $endDateTime->add(DateTimeParser::parse($vevent->DURATION->getValue()));
412
-			$dtend->setDateTime($endDateTime, $isFloating);
413
-		} elseif (!$vevent->DTSTART->hasTime()) {
414
-			$isFloating = $vevent->DTSTART->isFloating();
415
-			$dtend = clone $vevent->DTSTART;
416
-			$endDateTime = $dtend->getDateTime();
417
-			$endDateTime = $endDateTime->modify('+1 day');
418
-			$dtend->setDateTime($endDateTime, $isFloating);
419
-		} else {
420
-			$dtend = clone $vevent->DTSTART;
421
-		}
422
-
423
-		$isAllDay = $dtstart instanceof Property\ICalendar\Date;
424
-
425
-		/** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtstart */
426
-		/** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtend */
427
-		/** @var \DateTimeImmutable $dtstartDt */
428
-		$dtstartDt = $dtstart->getDateTime();
429
-		/** @var \DateTimeImmutable $dtendDt */
430
-		$dtendDt = $dtend->getDateTime();
431
-
432
-		$diff = $dtstartDt->diff($dtendDt);
433
-
434
-		$dtstartDt = new \DateTime($dtstartDt->format(\DateTimeInterface::ATOM));
435
-		$dtendDt = new \DateTime($dtendDt->format(\DateTimeInterface::ATOM));
436
-
437
-		if ($isAllDay) {
438
-			// One day event
439
-			if ($diff->days === 1) {
440
-				return $l10n->l('date', $dtstartDt, ['width' => 'medium']);
441
-			}
442
-
443
-			// DTEND is exclusive, so if the ics data says 2020-01-01 to 2020-01-05,
444
-			// the email should show 2020-01-01 to 2020-01-04.
445
-			$dtendDt->modify('-1 day');
446
-
447
-			//event that spans over multiple days
448
-			$localeStart = $l10n->l('date', $dtstartDt, ['width' => 'medium']);
449
-			$localeEnd = $l10n->l('date', $dtendDt, ['width' => 'medium']);
450
-
451
-			return $localeStart . ' - ' . $localeEnd;
452
-		}
453
-
454
-		/** @var Property\ICalendar\DateTime $dtstart */
455
-		/** @var Property\ICalendar\DateTime $dtend */
456
-		$isFloating = $dtstart->isFloating();
457
-		$startTimezone = $endTimezone = null;
458
-		if (!$isFloating) {
459
-			$prop = $dtstart->offsetGet('TZID');
460
-			if ($prop instanceof Parameter) {
461
-				$startTimezone = $prop->getValue();
462
-			}
463
-
464
-			$prop = $dtend->offsetGet('TZID');
465
-			if ($prop instanceof Parameter) {
466
-				$endTimezone = $prop->getValue();
467
-			}
468
-		}
469
-
470
-		$localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
471
-			$l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
472
-
473
-		// always show full date with timezone if timezones are different
474
-		if ($startTimezone !== $endTimezone) {
475
-			$localeEnd = $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
476
-
477
-			return $localeStart . ' (' . $startTimezone . ') - ' .
478
-				$localeEnd . ' (' . $endTimezone . ')';
479
-		}
480
-
481
-		// show only end time if date is the same
482
-		if ($this->isDayEqual($dtstartDt, $dtendDt)) {
483
-			$localeEnd = $l10n->l('time', $dtendDt, ['width' => 'short']);
484
-		} else {
485
-			$localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
486
-				$l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
487
-		}
488
-
489
-		return  $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')';
490
-	}
491
-
492
-	/**
493
-	 * @param \DateTime $dtStart
494
-	 * @param \DateTime $dtEnd
495
-	 * @return bool
496
-	 */
497
-	private function isDayEqual(\DateTime $dtStart, \DateTime $dtEnd) {
498
-		return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d');
499
-	}
500
-
501
-	/**
502
-	 * @param IEMailTemplate $template
503
-	 * @param IL10N $l10n
504
-	 * @param string $method
505
-	 * @param string $summary
506
-	 */
507
-	private function addSubjectAndHeading(IEMailTemplate $template, IL10N $l10n,
508
-										  $method, $summary) {
509
-		if ($method === self::METHOD_CANCEL) {
510
-			// TRANSLATORS Subject for email, when an invitation is cancelled. Ex: "Cancelled: {{Event Name}}"
511
-			$template->setSubject($l10n->t('Cancelled: %1$s', [$summary]));
512
-			$template->addHeading($l10n->t('Invitation canceled'));
513
-		} elseif ($method === self::METHOD_REPLY) {
514
-			// TRANSLATORS Subject for email, when an invitation is updated. Ex: "Re: {{Event Name}}"
515
-			$template->setSubject($l10n->t('Re: %1$s', [$summary]));
516
-			$template->addHeading($l10n->t('Invitation updated'));
517
-		} else {
518
-			// TRANSLATORS Subject for email, when an invitation is sent. Ex: "Invitation: {{Event Name}}"
519
-			$template->setSubject($l10n->t('Invitation: %1$s', [$summary]));
520
-			$template->addHeading($l10n->t('Invitation'));
521
-		}
522
-	}
523
-
524
-	/**
525
-	 * @param IEMailTemplate $template
526
-	 * @param IL10N $l10n
527
-	 * @param VEVENT $vevent
528
-	 */
529
-	private function addBulletList(IEMailTemplate $template, IL10N $l10n, $vevent) {
530
-		if ($vevent->SUMMARY) {
531
-			$template->addBodyListItem($vevent->SUMMARY, $l10n->t('Title:'),
532
-				$this->getAbsoluteImagePath('caldav/title.png'), '', '', self::IMIP_INDENT);
533
-		}
534
-		$meetingWhen = $this->generateWhenString($l10n, $vevent);
535
-		if ($meetingWhen) {
536
-			$template->addBodyListItem($meetingWhen, $l10n->t('Time:'),
537
-				$this->getAbsoluteImagePath('caldav/time.png'), '', '', self::IMIP_INDENT);
538
-		}
539
-		if ($vevent->LOCATION) {
540
-			$template->addBodyListItem($vevent->LOCATION, $l10n->t('Location:'),
541
-				$this->getAbsoluteImagePath('caldav/location.png'), '', '', self::IMIP_INDENT);
542
-		}
543
-		if ($vevent->URL) {
544
-			$url = $vevent->URL->getValue();
545
-			$template->addBodyListItem(sprintf('<a href="%s">%s</a>',
546
-				htmlspecialchars($url),
547
-				htmlspecialchars($url)),
548
-				$l10n->t('Link:'),
549
-				$this->getAbsoluteImagePath('caldav/link.png'),
550
-				$url, '', self::IMIP_INDENT);
551
-		}
552
-
553
-		$this->addAttendees($template, $l10n, $vevent);
554
-
555
-		/* Put description last, like an email body, since it can be arbitrarily long */
556
-		if ($vevent->DESCRIPTION) {
557
-			$template->addBodyListItem($vevent->DESCRIPTION->getValue(), $l10n->t('Description:'),
558
-				$this->getAbsoluteImagePath('caldav/description.png'), '', '', self::IMIP_INDENT);
559
-		}
560
-	}
561
-
562
-	/**
563
-	 * addAttendees: add organizer and attendee names/emails to iMip mail.
564
-	 *
565
-	 * Enable with DAV setting: invitation_list_attendees (default: no)
566
-	 *
567
-	 * The default is 'no', which matches old behavior, and is privacy preserving.
568
-	 *
569
-	 * To enable including attendees in invitation emails:
570
-	 *   % php occ config:app:set dav invitation_list_attendees --value yes
571
-	 *
572
-	 * @param IEMailTemplate $template
573
-	 * @param IL10N $l10n
574
-	 * @param Message $iTipMessage
575
-	 * @param int $lastOccurrence
576
-	 * @author brad2014 on github.com
577
-	 */
578
-
579
-	private function addAttendees(IEMailTemplate $template, IL10N $l10n, VEvent $vevent) {
580
-		if ($this->config->getAppValue('dav', 'invitation_list_attendees', 'no') === 'no') {
581
-			return;
582
-		}
583
-
584
-		if (isset($vevent->ORGANIZER)) {
585
-			/** @var Property\ICalendar\CalAddress $organizer */
586
-			$organizer = $vevent->ORGANIZER;
587
-			$organizerURI = $organizer->getNormalizedValue();
588
-			[$scheme,$organizerEmail] = explode(':', $organizerURI, 2); # strip off scheme mailto:
589
-			/** @var string|null $organizerName */
590
-			$organizerName = isset($organizer['CN']) ? $organizer['CN'] : null;
591
-			$organizerHTML = sprintf('<a href="%s">%s</a>',
592
-				htmlspecialchars($organizerURI),
593
-				htmlspecialchars($organizerName ?: $organizerEmail));
594
-			$organizerText = sprintf('%s <%s>', $organizerName, $organizerEmail);
595
-			if (isset($organizer['PARTSTAT'])) {
596
-				/** @var Parameter $partstat */
597
-				$partstat = $organizer['PARTSTAT'];
598
-				if (strcasecmp($partstat->getValue(), 'ACCEPTED') === 0) {
599
-					$organizerHTML .= ' ✔︎';
600
-					$organizerText .= ' ✔︎';
601
-				}
602
-			}
603
-			$template->addBodyListItem($organizerHTML, $l10n->t('Organizer:'),
604
-				$this->getAbsoluteImagePath('caldav/organizer.png'),
605
-				$organizerText, '', self::IMIP_INDENT);
606
-		}
607
-
608
-		$attendees = $vevent->select('ATTENDEE');
609
-		if (count($attendees) === 0) {
610
-			return;
611
-		}
612
-
613
-		$attendeesHTML = [];
614
-		$attendeesText = [];
615
-		foreach ($attendees as $attendee) {
616
-			$attendeeURI = $attendee->getNormalizedValue();
617
-			[$scheme,$attendeeEmail] = explode(':', $attendeeURI, 2); # strip off scheme mailto:
618
-			$attendeeName = isset($attendee['CN']) ? $attendee['CN'] : null;
619
-			$attendeeHTML = sprintf('<a href="%s">%s</a>',
620
-				htmlspecialchars($attendeeURI),
621
-				htmlspecialchars($attendeeName ?: $attendeeEmail));
622
-			$attendeeText = sprintf('%s <%s>', $attendeeName, $attendeeEmail);
623
-			if (isset($attendee['PARTSTAT'])
624
-				&& strcasecmp($attendee['PARTSTAT'], 'ACCEPTED') === 0) {
625
-				$attendeeHTML .= ' ✔︎';
626
-				$attendeeText .= ' ✔︎';
627
-			}
628
-			array_push($attendeesHTML, $attendeeHTML);
629
-			array_push($attendeesText, $attendeeText);
630
-		}
631
-
632
-		$template->addBodyListItem(implode('<br/>', $attendeesHTML), $l10n->t('Attendees:'),
633
-			$this->getAbsoluteImagePath('caldav/attendees.png'),
634
-			implode("\n", $attendeesText), '', self::IMIP_INDENT);
635
-	}
636
-
637
-	/**
638
-	 * @param IEMailTemplate $template
639
-	 * @param IL10N $l10n
640
-	 * @param Message $iTipMessage
641
-	 * @param int $lastOccurrence
642
-	 */
643
-	private function addResponseButtons(IEMailTemplate $template, IL10N $l10n,
644
-										Message $iTipMessage, $lastOccurrence) {
645
-		$token = $this->createInvitationToken($iTipMessage, $lastOccurrence);
646
-
647
-		$template->addBodyButtonGroup(
648
-			$l10n->t('Accept'),
649
-			$this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.accept', [
650
-				'token' => $token,
651
-			]),
652
-			$l10n->t('Decline'),
653
-			$this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.decline', [
654
-				'token' => $token,
655
-			])
656
-		);
657
-
658
-		$moreOptionsURL = $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.options', [
659
-			'token' => $token,
660
-		]);
661
-		$html = vsprintf('<small><a href="%s">%s</a></small>', [
662
-			$moreOptionsURL, $l10n->t('More options …')
663
-		]);
664
-		$text = $l10n->t('More options at %s', [$moreOptionsURL]);
665
-
666
-		$template->addBodyText($html, $text);
667
-	}
668
-
669
-	/**
670
-	 * @param string $path
671
-	 * @return string
672
-	 */
673
-	private function getAbsoluteImagePath($path) {
674
-		return $this->urlGenerator->getAbsoluteURL(
675
-			$this->urlGenerator->imagePath('core', $path)
676
-		);
677
-	}
678
-
679
-	/**
680
-	 * @param Message $iTipMessage
681
-	 * @param int $lastOccurrence
682
-	 * @return string
683
-	 */
684
-	private function createInvitationToken(Message $iTipMessage, $lastOccurrence):string {
685
-		$token = $this->random->generate(60, ISecureRandom::CHAR_ALPHANUMERIC);
686
-
687
-		/** @var VEvent $vevent */
688
-		$vevent = $iTipMessage->message->VEVENT;
689
-		$attendee = $iTipMessage->recipient;
690
-		$organizer = $iTipMessage->sender;
691
-		$sequence = $iTipMessage->sequence;
692
-		$recurrenceId = isset($vevent->{'RECURRENCE-ID'}) ?
693
-			$vevent->{'RECURRENCE-ID'}->serialize() : null;
694
-		$uid = $vevent->{'UID'};
695
-
696
-		$query = $this->db->getQueryBuilder();
697
-		$query->insert('calendar_invitations')
698
-			->values([
699
-				'token' => $query->createNamedParameter($token),
700
-				'attendee' => $query->createNamedParameter($attendee),
701
-				'organizer' => $query->createNamedParameter($organizer),
702
-				'sequence' => $query->createNamedParameter($sequence),
703
-				'recurrenceid' => $query->createNamedParameter($recurrenceId),
704
-				'expiration' => $query->createNamedParameter($lastOccurrence),
705
-				'uid' => $query->createNamedParameter($uid)
706
-			])
707
-			->execute();
708
-
709
-		return $token;
710
-	}
262
+            $recipientDomain = substr(strrchr($recipient, "@"), 1);
263
+            $invitationLinkRecipients = explode(',', preg_replace('/\s+/', '', strtolower($this->config->getAppValue('dav', 'invitation_link_recipients', 'yes'))));
264
+
265
+            if (strcmp('yes', $invitationLinkRecipients[0]) === 0
266
+                 || in_array(strtolower($recipient), $invitationLinkRecipients)
267
+                 || in_array(strtolower($recipientDomain), $invitationLinkRecipients)) {
268
+                $this->addResponseButtons($template, $l10n, $iTipMessage, $lastOccurrence);
269
+            }
270
+        }
271
+
272
+        $template->addFooter();
273
+
274
+        $message->useTemplate($template);
275
+
276
+        $attachment = $this->mailer->createAttachment(
277
+            $iTipMessage->message->serialize(),
278
+            'event.ics',// TODO(leon): Make file name unique, e.g. add event id
279
+            'text/calendar; method=' . $iTipMessage->method
280
+        );
281
+        $message->attach($attachment);
282
+
283
+        try {
284
+            $failed = $this->mailer->send($message);
285
+            $iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
286
+            if ($failed) {
287
+                $this->logger->error('Unable to deliver message to {failed}', ['app' => 'dav', 'failed' => implode(', ', $failed)]);
288
+                $iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
289
+            }
290
+        } catch (\Exception $ex) {
291
+            $this->logger->error($ex->getMessage(), ['app' => 'dav', 'exception' => $ex]);
292
+            $iTipMessage->scheduleStatus = '5.0; EMail delivery failed';
293
+        }
294
+    }
295
+
296
+    /**
297
+     * check if event took place in the past already
298
+     * @param VCalendar $vObject
299
+     * @return int
300
+     */
301
+    private function getLastOccurrence(VCalendar $vObject) {
302
+        /** @var VEvent $component */
303
+        $component = $vObject->VEVENT;
304
+
305
+        $firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp();
306
+        // Finding the last occurrence is a bit harder
307
+        if (!isset($component->RRULE)) {
308
+            if (isset($component->DTEND)) {
309
+                $lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp();
310
+            } elseif (isset($component->DURATION)) {
311
+                /** @var \DateTime $endDate */
312
+                $endDate = clone $component->DTSTART->getDateTime();
313
+                // $component->DTEND->getDateTime() returns DateTimeImmutable
314
+                $endDate = $endDate->add(DateTimeParser::parse($component->DURATION->getValue()));
315
+                $lastOccurrence = $endDate->getTimestamp();
316
+            } elseif (!$component->DTSTART->hasTime()) {
317
+                /** @var \DateTime $endDate */
318
+                $endDate = clone $component->DTSTART->getDateTime();
319
+                // $component->DTSTART->getDateTime() returns DateTimeImmutable
320
+                $endDate = $endDate->modify('+1 day');
321
+                $lastOccurrence = $endDate->getTimestamp();
322
+            } else {
323
+                $lastOccurrence = $firstOccurrence;
324
+            }
325
+        } else {
326
+            $it = new EventIterator($vObject, (string)$component->UID);
327
+            $maxDate = new \DateTime(self::MAX_DATE);
328
+            if ($it->isInfinite()) {
329
+                $lastOccurrence = $maxDate->getTimestamp();
330
+            } else {
331
+                $end = $it->getDtEnd();
332
+                while ($it->valid() && $end < $maxDate) {
333
+                    $end = $it->getDtEnd();
334
+                    $it->next();
335
+                }
336
+                $lastOccurrence = $end->getTimestamp();
337
+            }
338
+        }
339
+
340
+        return $lastOccurrence;
341
+    }
342
+
343
+    /**
344
+     * @param Message $iTipMessage
345
+     * @return null|Property
346
+     */
347
+    private function getCurrentAttendee(Message $iTipMessage) {
348
+        /** @var VEvent $vevent */
349
+        $vevent = $iTipMessage->message->VEVENT;
350
+        $attendees = $vevent->select('ATTENDEE');
351
+        foreach ($attendees as $attendee) {
352
+            /** @var Property $attendee */
353
+            if (strcasecmp($attendee->getValue(), $iTipMessage->recipient) === 0) {
354
+                return $attendee;
355
+            }
356
+        }
357
+        return null;
358
+    }
359
+
360
+    /**
361
+     * @param string $default
362
+     * @param Property|null $attendee
363
+     * @return string
364
+     */
365
+    private function getAttendeeLangOrDefault($default, Property $attendee = null) {
366
+        if ($attendee !== null) {
367
+            $lang = $attendee->offsetGet('LANGUAGE');
368
+            if ($lang instanceof Parameter) {
369
+                return $lang->getValue();
370
+            }
371
+        }
372
+        return $default;
373
+    }
374
+
375
+    /**
376
+     * @param Property|null $attendee
377
+     * @return bool
378
+     */
379
+    private function getAttendeeRsvpOrReqForParticipant(Property $attendee = null) {
380
+        if ($attendee !== null) {
381
+            $rsvp = $attendee->offsetGet('RSVP');
382
+            if (($rsvp instanceof Parameter) && (strcasecmp($rsvp->getValue(), 'TRUE') === 0)) {
383
+                return true;
384
+            }
385
+            $role = $attendee->offsetGet('ROLE');
386
+            // @see https://datatracker.ietf.org/doc/html/rfc5545#section-3.2.16
387
+            // Attendees without a role are assumed required and should receive an invitation link even if they have no RSVP set
388
+            if ($role === null
389
+                || (($role instanceof Parameter) && (strcasecmp($role->getValue(), 'REQ-PARTICIPANT') === 0))
390
+                || (($role instanceof Parameter) && (strcasecmp($role->getValue(), 'OPT-PARTICIPANT') === 0))
391
+            ) {
392
+                return true;
393
+            }
394
+        }
395
+        // RFC 5545 3.2.17: default RSVP is false
396
+        return false;
397
+    }
398
+
399
+    /**
400
+     * @param IL10N $l10n
401
+     * @param VEvent $vevent
402
+     */
403
+    private function generateWhenString(IL10N $l10n, VEvent $vevent) {
404
+        $dtstart = $vevent->DTSTART;
405
+        if (isset($vevent->DTEND)) {
406
+            $dtend = $vevent->DTEND;
407
+        } elseif (isset($vevent->DURATION)) {
408
+            $isFloating = $vevent->DTSTART->isFloating();
409
+            $dtend = clone $vevent->DTSTART;
410
+            $endDateTime = $dtend->getDateTime();
411
+            $endDateTime = $endDateTime->add(DateTimeParser::parse($vevent->DURATION->getValue()));
412
+            $dtend->setDateTime($endDateTime, $isFloating);
413
+        } elseif (!$vevent->DTSTART->hasTime()) {
414
+            $isFloating = $vevent->DTSTART->isFloating();
415
+            $dtend = clone $vevent->DTSTART;
416
+            $endDateTime = $dtend->getDateTime();
417
+            $endDateTime = $endDateTime->modify('+1 day');
418
+            $dtend->setDateTime($endDateTime, $isFloating);
419
+        } else {
420
+            $dtend = clone $vevent->DTSTART;
421
+        }
422
+
423
+        $isAllDay = $dtstart instanceof Property\ICalendar\Date;
424
+
425
+        /** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtstart */
426
+        /** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtend */
427
+        /** @var \DateTimeImmutable $dtstartDt */
428
+        $dtstartDt = $dtstart->getDateTime();
429
+        /** @var \DateTimeImmutable $dtendDt */
430
+        $dtendDt = $dtend->getDateTime();
431
+
432
+        $diff = $dtstartDt->diff($dtendDt);
433
+
434
+        $dtstartDt = new \DateTime($dtstartDt->format(\DateTimeInterface::ATOM));
435
+        $dtendDt = new \DateTime($dtendDt->format(\DateTimeInterface::ATOM));
436
+
437
+        if ($isAllDay) {
438
+            // One day event
439
+            if ($diff->days === 1) {
440
+                return $l10n->l('date', $dtstartDt, ['width' => 'medium']);
441
+            }
442
+
443
+            // DTEND is exclusive, so if the ics data says 2020-01-01 to 2020-01-05,
444
+            // the email should show 2020-01-01 to 2020-01-04.
445
+            $dtendDt->modify('-1 day');
446
+
447
+            //event that spans over multiple days
448
+            $localeStart = $l10n->l('date', $dtstartDt, ['width' => 'medium']);
449
+            $localeEnd = $l10n->l('date', $dtendDt, ['width' => 'medium']);
450
+
451
+            return $localeStart . ' - ' . $localeEnd;
452
+        }
453
+
454
+        /** @var Property\ICalendar\DateTime $dtstart */
455
+        /** @var Property\ICalendar\DateTime $dtend */
456
+        $isFloating = $dtstart->isFloating();
457
+        $startTimezone = $endTimezone = null;
458
+        if (!$isFloating) {
459
+            $prop = $dtstart->offsetGet('TZID');
460
+            if ($prop instanceof Parameter) {
461
+                $startTimezone = $prop->getValue();
462
+            }
463
+
464
+            $prop = $dtend->offsetGet('TZID');
465
+            if ($prop instanceof Parameter) {
466
+                $endTimezone = $prop->getValue();
467
+            }
468
+        }
469
+
470
+        $localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
471
+            $l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
472
+
473
+        // always show full date with timezone if timezones are different
474
+        if ($startTimezone !== $endTimezone) {
475
+            $localeEnd = $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
476
+
477
+            return $localeStart . ' (' . $startTimezone . ') - ' .
478
+                $localeEnd . ' (' . $endTimezone . ')';
479
+        }
480
+
481
+        // show only end time if date is the same
482
+        if ($this->isDayEqual($dtstartDt, $dtendDt)) {
483
+            $localeEnd = $l10n->l('time', $dtendDt, ['width' => 'short']);
484
+        } else {
485
+            $localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
486
+                $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
487
+        }
488
+
489
+        return  $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')';
490
+    }
491
+
492
+    /**
493
+     * @param \DateTime $dtStart
494
+     * @param \DateTime $dtEnd
495
+     * @return bool
496
+     */
497
+    private function isDayEqual(\DateTime $dtStart, \DateTime $dtEnd) {
498
+        return $dtStart->format('Y-m-d') === $dtEnd->format('Y-m-d');
499
+    }
500
+
501
+    /**
502
+     * @param IEMailTemplate $template
503
+     * @param IL10N $l10n
504
+     * @param string $method
505
+     * @param string $summary
506
+     */
507
+    private function addSubjectAndHeading(IEMailTemplate $template, IL10N $l10n,
508
+                                            $method, $summary) {
509
+        if ($method === self::METHOD_CANCEL) {
510
+            // TRANSLATORS Subject for email, when an invitation is cancelled. Ex: "Cancelled: {{Event Name}}"
511
+            $template->setSubject($l10n->t('Cancelled: %1$s', [$summary]));
512
+            $template->addHeading($l10n->t('Invitation canceled'));
513
+        } elseif ($method === self::METHOD_REPLY) {
514
+            // TRANSLATORS Subject for email, when an invitation is updated. Ex: "Re: {{Event Name}}"
515
+            $template->setSubject($l10n->t('Re: %1$s', [$summary]));
516
+            $template->addHeading($l10n->t('Invitation updated'));
517
+        } else {
518
+            // TRANSLATORS Subject for email, when an invitation is sent. Ex: "Invitation: {{Event Name}}"
519
+            $template->setSubject($l10n->t('Invitation: %1$s', [$summary]));
520
+            $template->addHeading($l10n->t('Invitation'));
521
+        }
522
+    }
523
+
524
+    /**
525
+     * @param IEMailTemplate $template
526
+     * @param IL10N $l10n
527
+     * @param VEVENT $vevent
528
+     */
529
+    private function addBulletList(IEMailTemplate $template, IL10N $l10n, $vevent) {
530
+        if ($vevent->SUMMARY) {
531
+            $template->addBodyListItem($vevent->SUMMARY, $l10n->t('Title:'),
532
+                $this->getAbsoluteImagePath('caldav/title.png'), '', '', self::IMIP_INDENT);
533
+        }
534
+        $meetingWhen = $this->generateWhenString($l10n, $vevent);
535
+        if ($meetingWhen) {
536
+            $template->addBodyListItem($meetingWhen, $l10n->t('Time:'),
537
+                $this->getAbsoluteImagePath('caldav/time.png'), '', '', self::IMIP_INDENT);
538
+        }
539
+        if ($vevent->LOCATION) {
540
+            $template->addBodyListItem($vevent->LOCATION, $l10n->t('Location:'),
541
+                $this->getAbsoluteImagePath('caldav/location.png'), '', '', self::IMIP_INDENT);
542
+        }
543
+        if ($vevent->URL) {
544
+            $url = $vevent->URL->getValue();
545
+            $template->addBodyListItem(sprintf('<a href="%s">%s</a>',
546
+                htmlspecialchars($url),
547
+                htmlspecialchars($url)),
548
+                $l10n->t('Link:'),
549
+                $this->getAbsoluteImagePath('caldav/link.png'),
550
+                $url, '', self::IMIP_INDENT);
551
+        }
552
+
553
+        $this->addAttendees($template, $l10n, $vevent);
554
+
555
+        /* Put description last, like an email body, since it can be arbitrarily long */
556
+        if ($vevent->DESCRIPTION) {
557
+            $template->addBodyListItem($vevent->DESCRIPTION->getValue(), $l10n->t('Description:'),
558
+                $this->getAbsoluteImagePath('caldav/description.png'), '', '', self::IMIP_INDENT);
559
+        }
560
+    }
561
+
562
+    /**
563
+     * addAttendees: add organizer and attendee names/emails to iMip mail.
564
+     *
565
+     * Enable with DAV setting: invitation_list_attendees (default: no)
566
+     *
567
+     * The default is 'no', which matches old behavior, and is privacy preserving.
568
+     *
569
+     * To enable including attendees in invitation emails:
570
+     *   % php occ config:app:set dav invitation_list_attendees --value yes
571
+     *
572
+     * @param IEMailTemplate $template
573
+     * @param IL10N $l10n
574
+     * @param Message $iTipMessage
575
+     * @param int $lastOccurrence
576
+     * @author brad2014 on github.com
577
+     */
578
+
579
+    private function addAttendees(IEMailTemplate $template, IL10N $l10n, VEvent $vevent) {
580
+        if ($this->config->getAppValue('dav', 'invitation_list_attendees', 'no') === 'no') {
581
+            return;
582
+        }
583
+
584
+        if (isset($vevent->ORGANIZER)) {
585
+            /** @var Property\ICalendar\CalAddress $organizer */
586
+            $organizer = $vevent->ORGANIZER;
587
+            $organizerURI = $organizer->getNormalizedValue();
588
+            [$scheme,$organizerEmail] = explode(':', $organizerURI, 2); # strip off scheme mailto:
589
+            /** @var string|null $organizerName */
590
+            $organizerName = isset($organizer['CN']) ? $organizer['CN'] : null;
591
+            $organizerHTML = sprintf('<a href="%s">%s</a>',
592
+                htmlspecialchars($organizerURI),
593
+                htmlspecialchars($organizerName ?: $organizerEmail));
594
+            $organizerText = sprintf('%s <%s>', $organizerName, $organizerEmail);
595
+            if (isset($organizer['PARTSTAT'])) {
596
+                /** @var Parameter $partstat */
597
+                $partstat = $organizer['PARTSTAT'];
598
+                if (strcasecmp($partstat->getValue(), 'ACCEPTED') === 0) {
599
+                    $organizerHTML .= ' ✔︎';
600
+                    $organizerText .= ' ✔︎';
601
+                }
602
+            }
603
+            $template->addBodyListItem($organizerHTML, $l10n->t('Organizer:'),
604
+                $this->getAbsoluteImagePath('caldav/organizer.png'),
605
+                $organizerText, '', self::IMIP_INDENT);
606
+        }
607
+
608
+        $attendees = $vevent->select('ATTENDEE');
609
+        if (count($attendees) === 0) {
610
+            return;
611
+        }
612
+
613
+        $attendeesHTML = [];
614
+        $attendeesText = [];
615
+        foreach ($attendees as $attendee) {
616
+            $attendeeURI = $attendee->getNormalizedValue();
617
+            [$scheme,$attendeeEmail] = explode(':', $attendeeURI, 2); # strip off scheme mailto:
618
+            $attendeeName = isset($attendee['CN']) ? $attendee['CN'] : null;
619
+            $attendeeHTML = sprintf('<a href="%s">%s</a>',
620
+                htmlspecialchars($attendeeURI),
621
+                htmlspecialchars($attendeeName ?: $attendeeEmail));
622
+            $attendeeText = sprintf('%s <%s>', $attendeeName, $attendeeEmail);
623
+            if (isset($attendee['PARTSTAT'])
624
+                && strcasecmp($attendee['PARTSTAT'], 'ACCEPTED') === 0) {
625
+                $attendeeHTML .= ' ✔︎';
626
+                $attendeeText .= ' ✔︎';
627
+            }
628
+            array_push($attendeesHTML, $attendeeHTML);
629
+            array_push($attendeesText, $attendeeText);
630
+        }
631
+
632
+        $template->addBodyListItem(implode('<br/>', $attendeesHTML), $l10n->t('Attendees:'),
633
+            $this->getAbsoluteImagePath('caldav/attendees.png'),
634
+            implode("\n", $attendeesText), '', self::IMIP_INDENT);
635
+    }
636
+
637
+    /**
638
+     * @param IEMailTemplate $template
639
+     * @param IL10N $l10n
640
+     * @param Message $iTipMessage
641
+     * @param int $lastOccurrence
642
+     */
643
+    private function addResponseButtons(IEMailTemplate $template, IL10N $l10n,
644
+                                        Message $iTipMessage, $lastOccurrence) {
645
+        $token = $this->createInvitationToken($iTipMessage, $lastOccurrence);
646
+
647
+        $template->addBodyButtonGroup(
648
+            $l10n->t('Accept'),
649
+            $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.accept', [
650
+                'token' => $token,
651
+            ]),
652
+            $l10n->t('Decline'),
653
+            $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.decline', [
654
+                'token' => $token,
655
+            ])
656
+        );
657
+
658
+        $moreOptionsURL = $this->urlGenerator->linkToRouteAbsolute('dav.invitation_response.options', [
659
+            'token' => $token,
660
+        ]);
661
+        $html = vsprintf('<small><a href="%s">%s</a></small>', [
662
+            $moreOptionsURL, $l10n->t('More options …')
663
+        ]);
664
+        $text = $l10n->t('More options at %s', [$moreOptionsURL]);
665
+
666
+        $template->addBodyText($html, $text);
667
+    }
668
+
669
+    /**
670
+     * @param string $path
671
+     * @return string
672
+     */
673
+    private function getAbsoluteImagePath($path) {
674
+        return $this->urlGenerator->getAbsoluteURL(
675
+            $this->urlGenerator->imagePath('core', $path)
676
+        );
677
+    }
678
+
679
+    /**
680
+     * @param Message $iTipMessage
681
+     * @param int $lastOccurrence
682
+     * @return string
683
+     */
684
+    private function createInvitationToken(Message $iTipMessage, $lastOccurrence):string {
685
+        $token = $this->random->generate(60, ISecureRandom::CHAR_ALPHANUMERIC);
686
+
687
+        /** @var VEvent $vevent */
688
+        $vevent = $iTipMessage->message->VEVENT;
689
+        $attendee = $iTipMessage->recipient;
690
+        $organizer = $iTipMessage->sender;
691
+        $sequence = $iTipMessage->sequence;
692
+        $recurrenceId = isset($vevent->{'RECURRENCE-ID'}) ?
693
+            $vevent->{'RECURRENCE-ID'}->serialize() : null;
694
+        $uid = $vevent->{'UID'};
695
+
696
+        $query = $this->db->getQueryBuilder();
697
+        $query->insert('calendar_invitations')
698
+            ->values([
699
+                'token' => $query->createNamedParameter($token),
700
+                'attendee' => $query->createNamedParameter($attendee),
701
+                'organizer' => $query->createNamedParameter($organizer),
702
+                'sequence' => $query->createNamedParameter($sequence),
703
+                'recurrenceid' => $query->createNamedParameter($recurrenceId),
704
+                'expiration' => $query->createNamedParameter($lastOccurrence),
705
+                'uid' => $query->createNamedParameter($uid)
706
+            ])
707
+            ->execute();
708
+
709
+        return $token;
710
+    }
711 711
 }
Please login to merge, or discard this patch.
Spacing   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
 
177 177
 		/** @var Parameter|string|null $senderName */
178 178
 		$senderName = $iTipMessage->senderName ?: null;
179
-		if($senderName instanceof Parameter) {
179
+		if ($senderName instanceof Parameter) {
180 180
 			$senderName = $senderName->getValue() ?? null;
181 181
 		}
182 182
 
@@ -215,11 +215,11 @@  discard block
 block discarded – undo
215 215
 		}
216 216
 
217 217
 		$data = [
218
-			'attendee_name' => (string)$meetingAttendeeName ?: $defaultVal,
219
-			'invitee_name' => (string)$meetingInviteeName ?: $defaultVal,
220
-			'meeting_title' => (string)$meetingTitle ?: $defaultVal,
221
-			'meeting_description' => (string)$meetingDescription ?: $defaultVal,
222
-			'meeting_url' => (string)$meetingUrl ?: $defaultVal,
218
+			'attendee_name' => (string) $meetingAttendeeName ?: $defaultVal,
219
+			'invitee_name' => (string) $meetingInviteeName ?: $defaultVal,
220
+			'meeting_title' => (string) $meetingTitle ?: $defaultVal,
221
+			'meeting_description' => (string) $meetingDescription ?: $defaultVal,
222
+			'meeting_url' => (string) $meetingUrl ?: $defaultVal,
223 223
 		];
224 224
 
225 225
 		$fromEMail = Util::getDefaultEmailAddress('invitations-noreply');
@@ -230,7 +230,7 @@  discard block
 block discarded – undo
230 230
 			->setTo([$recipient => $recipientName])
231 231
 			->setReplyTo([$sender => $senderName]);
232 232
 
233
-		$template = $this->mailer->createEMailTemplate('dav.calendarInvite.' . $method, $data);
233
+		$template = $this->mailer->createEMailTemplate('dav.calendarInvite.'.$method, $data);
234 234
 		$template->addHeader();
235 235
 
236 236
 		$summary = ((string) $summary !== '') ? (string) $summary : $l10n->t('Untitled event');
@@ -275,8 +275,8 @@  discard block
 block discarded – undo
275 275
 
276 276
 		$attachment = $this->mailer->createAttachment(
277 277
 			$iTipMessage->message->serialize(),
278
-			'event.ics',// TODO(leon): Make file name unique, e.g. add event id
279
-			'text/calendar; method=' . $iTipMessage->method
278
+			'event.ics', // TODO(leon): Make file name unique, e.g. add event id
279
+			'text/calendar; method='.$iTipMessage->method
280 280
 		);
281 281
 		$message->attach($attachment);
282 282
 
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
 				$lastOccurrence = $firstOccurrence;
324 324
 			}
325 325
 		} else {
326
-			$it = new EventIterator($vObject, (string)$component->UID);
326
+			$it = new EventIterator($vObject, (string) $component->UID);
327 327
 			$maxDate = new \DateTime(self::MAX_DATE);
328 328
 			if ($it->isInfinite()) {
329 329
 				$lastOccurrence = $maxDate->getTimestamp();
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
 			$localeStart = $l10n->l('date', $dtstartDt, ['width' => 'medium']);
449 449
 			$localeEnd = $l10n->l('date', $dtendDt, ['width' => 'medium']);
450 450
 
451
-			return $localeStart . ' - ' . $localeEnd;
451
+			return $localeStart.' - '.$localeEnd;
452 452
 		}
453 453
 
454 454
 		/** @var Property\ICalendar\DateTime $dtstart */
@@ -467,26 +467,26 @@  discard block
 block discarded – undo
467 467
 			}
468 468
 		}
469 469
 
470
-		$localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' .
470
+		$localeStart = $l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']).', '.
471 471
 			$l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']);
472 472
 
473 473
 		// always show full date with timezone if timezones are different
474 474
 		if ($startTimezone !== $endTimezone) {
475 475
 			$localeEnd = $l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
476 476
 
477
-			return $localeStart . ' (' . $startTimezone . ') - ' .
478
-				$localeEnd . ' (' . $endTimezone . ')';
477
+			return $localeStart.' ('.$startTimezone.') - '.
478
+				$localeEnd.' ('.$endTimezone.')';
479 479
 		}
480 480
 
481 481
 		// show only end time if date is the same
482 482
 		if ($this->isDayEqual($dtstartDt, $dtendDt)) {
483 483
 			$localeEnd = $l10n->l('time', $dtendDt, ['width' => 'short']);
484 484
 		} else {
485
-			$localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' .
485
+			$localeEnd = $l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']).', '.
486 486
 				$l10n->l('datetime', $dtendDt, ['width' => 'medium|short']);
487 487
 		}
488 488
 
489
-		return  $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')';
489
+		return  $localeStart.' - '.$localeEnd.' ('.$startTimezone.')';
490 490
 	}
491 491
 
492 492
 	/**
@@ -585,7 +585,7 @@  discard block
 block discarded – undo
585 585
 			/** @var Property\ICalendar\CalAddress $organizer */
586 586
 			$organizer = $vevent->ORGANIZER;
587 587
 			$organizerURI = $organizer->getNormalizedValue();
588
-			[$scheme,$organizerEmail] = explode(':', $organizerURI, 2); # strip off scheme mailto:
588
+			[$scheme, $organizerEmail] = explode(':', $organizerURI, 2); # strip off scheme mailto:
589 589
 			/** @var string|null $organizerName */
590 590
 			$organizerName = isset($organizer['CN']) ? $organizer['CN'] : null;
591 591
 			$organizerHTML = sprintf('<a href="%s">%s</a>',
@@ -614,7 +614,7 @@  discard block
 block discarded – undo
614 614
 		$attendeesText = [];
615 615
 		foreach ($attendees as $attendee) {
616 616
 			$attendeeURI = $attendee->getNormalizedValue();
617
-			[$scheme,$attendeeEmail] = explode(':', $attendeeURI, 2); # strip off scheme mailto:
617
+			[$scheme, $attendeeEmail] = explode(':', $attendeeURI, 2); # strip off scheme mailto:
618 618
 			$attendeeName = isset($attendee['CN']) ? $attendee['CN'] : null;
619 619
 			$attendeeHTML = sprintf('<a href="%s">%s</a>',
620 620
 				htmlspecialchars($attendeeURI),
Please login to merge, or discard this patch.
apps/settings/templates/settings/admin/additional-mail.php 2 patches
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -25,23 +25,23 @@  discard block
 block discarded – undo
25 25
 /** @var array $_ */
26 26
 
27 27
 $mail_smtpsecure = [
28
-	'' => $l->t('None'),
29
-	'ssl' => $l->t('SSL/TLS')
28
+    '' => $l->t('None'),
29
+    'ssl' => $l->t('SSL/TLS')
30 30
 ];
31 31
 
32 32
 $mail_smtpmode = [
33
-	['smtp', 'SMTP'],
33
+    ['smtp', 'SMTP'],
34 34
 ];
35 35
 if ($_['sendmail_is_available']) {
36
-	$mail_smtpmode[] = ['sendmail', 'Sendmail'];
36
+    $mail_smtpmode[] = ['sendmail', 'Sendmail'];
37 37
 }
38 38
 if ($_['mail_smtpmode'] === 'qmail') {
39
-	$mail_smtpmode[] = ['qmail', 'qmail'];
39
+    $mail_smtpmode[] = ['qmail', 'qmail'];
40 40
 }
41 41
 
42 42
 $mail_sendmailmode = [
43
-	'smtp' => 'smtp (-bs)',
44
-	'pipe' => 'pipe (-t)'
43
+    'smtp' => 'smtp (-bs)',
44
+    'pipe' => 'pipe (-t)'
45 45
 ];
46 46
 
47 47
 ?>
@@ -59,29 +59,29 @@  discard block
 block discarded – undo
59 59
 			<label for="mail_smtpmode"><?php p($l->t('Send mode')); ?></label>
60 60
 			<select name="mail_smtpmode" id="mail_smtpmode">
61 61
 				<?php foreach ($mail_smtpmode as $smtpmode):
62
-					$selected = '';
63
-					if ($smtpmode[0] == $_['mail_smtpmode']):
64
-						$selected = 'selected="selected"';
65
-					endif; ?>
62
+                    $selected = '';
63
+                    if ($smtpmode[0] == $_['mail_smtpmode']):
64
+                        $selected = 'selected="selected"';
65
+                    endif; ?>
66 66
 					<option value="<?php p($smtpmode[0])?>" <?php p($selected) ?>><?php p($smtpmode[1]) ?></option>
67 67
 				<?php endforeach;?>
68 68
 			</select>
69 69
 
70 70
 			<label id="mail_smtpsecure_label" for="mail_smtpsecure"
71 71
 				<?php if ($_['mail_smtpmode'] !== 'smtp') {
72
-						print_unescaped(' class="hidden"');
73
-					} ?>>
72
+                        print_unescaped(' class="hidden"');
73
+                    } ?>>
74 74
 				<?php p($l->t('Encryption')); ?>
75 75
 			</label>
76 76
 			<select name="mail_smtpsecure" id="mail_smtpsecure"
77 77
 				<?php if ($_['mail_smtpmode'] !== 'smtp') {
78
-						print_unescaped(' class="hidden"');
79
-					} ?>>
78
+                        print_unescaped(' class="hidden"');
79
+                    } ?>>
80 80
 				<?php foreach ($mail_smtpsecure as $secure => $name):
81
-					$selected = '';
82
-					if ($secure == $_['mail_smtpsecure']):
83
-						$selected = 'selected="selected"';
84
-					endif; ?>
81
+                    $selected = '';
82
+                    if ($secure == $_['mail_smtpsecure']):
83
+                        $selected = 'selected="selected"';
84
+                    endif; ?>
85 85
 					<option value="<?php p($secure)?>" <?php p($selected) ?>><?php p($name) ?></option>
86 86
 				<?php endforeach;?>
87 87
 			</select>
@@ -107,8 +107,8 @@  discard block
 block discarded – undo
107 107
 <!--lo-->
108 108
 
109 109
 		<p id="setting_smtphost" <?php if ($_['mail_smtpmode'] !== 'smtp') {
110
-						print_unescaped(' class="hidden"');
111
-					} ?>>
110
+                        print_unescaped(' class="hidden"');
111
+                    } ?>>
112 112
 			<label for="mail_smtphost"><?php p($l->t('Server address')); ?></label>
113 113
 			<input type="text" name="mail_smtphost" id="mail_smtphost" placeholder="smtp.example.com"
114 114
 				   value="<?php p($_['mail_smtphost']) ?>" />
@@ -119,8 +119,8 @@  discard block
 block discarded – undo
119 119
 	</form>
120 120
 	<form class="mail_settings" id="mail_credentials_settings">
121 121
 		<p id="mail_credentials" <?php if ($_['mail_smtpmode'] !== 'smtp') {
122
-						print_unescaped(' class="hidden"');
123
-					} ?>>
122
+                        print_unescaped(' class="hidden"');
123
+                    } ?>>
124 124
 			<label for="mail_smtpname"><?php p($l->t('Credentials')); ?></label>
125 125
 			<input type="text" name="mail_smtpname" id="mail_smtpname" placeholder="<?php p($l->t('SMTP Username'))?>"
126 126
 				   value="<?php p($_['mail_smtpname']) ?>" />
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -48,9 +48,9 @@  discard block
 block discarded – undo
48 48
 
49 49
 <div class="section" id="mail_general_settings">
50 50
 	<form id="mail_general_settings_form" class="mail_settings">
51
-		<h2><?php p($l->t('Email server'));?></h2>
51
+		<h2><?php p($l->t('Email server')); ?></h2>
52 52
 		<a target="_blank" rel="noreferrer noopener" class="icon-info"
53
-		   title="<?php p($l->t('Open documentation'));?>"
53
+		   title="<?php p($l->t('Open documentation')); ?>"
54 54
 		   href="<?php p(link_to_docs('admin-email')); ?>"></a>
55 55
 		<p class="settings-hint"><?php p($l->t('It is important to set up this server to be able to send emails, like for password reset and notifications.')); ?></p>
56 56
 		<p><span id="mail_settings_msg" class="msg"></span></p>
@@ -64,7 +64,7 @@  discard block
 block discarded – undo
64 64
 						$selected = 'selected="selected"';
65 65
 					endif; ?>
66 66
 					<option value="<?php p($smtpmode[0])?>" <?php p($selected) ?>><?php p($smtpmode[1]) ?></option>
67
-				<?php endforeach;?>
67
+				<?php endforeach; ?>
68 68
 			</select>
69 69
 
70 70
 			<label id="mail_smtpsecure_label" for="mail_smtpsecure"
@@ -83,7 +83,7 @@  discard block
 block discarded – undo
83 83
 						$selected = 'selected="selected"';
84 84
 					endif; ?>
85 85
 					<option value="<?php p($secure)?>" <?php p($selected) ?>><?php p($name) ?></option>
86
-				<?php endforeach;?>
86
+				<?php endforeach; ?>
87 87
 			</select>
88 88
 
89 89
 			<label id="mail_sendmailmode_label" for="mail_sendmailmode" class="<?= $_['mail_smtpmode'] !== 'sendmail' ? 'hidden' : '' ?>">
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
 			<select name="mail_sendmailmode" id="mail_sendmailmode" class="<?= $_['mail_smtpmode'] !== 'sendmail' ? 'hidden' : '' ?>">
93 93
 				<?php foreach ($mail_sendmailmode as $sendmailmodeValue => $sendmailmodeLabel): ?>
94 94
 					<option value="<?php p($sendmailmodeValue)?>" <?= $sendmailmodeValue === $_['mail_sendmailmode'] ? 'selected="selected"' : '' ?>><?php p($sendmailmodeLabel) ?></option>
95
-				<?php endforeach;?>
95
+				<?php endforeach; ?>
96 96
 			</select>
97 97
 		</p>
98 98
 
Please login to merge, or discard this patch.
apps/settings/lib/Settings/Admin/Mail.php 1 patch
Indentation   +60 added lines, -60 removed lines patch added patch discarded remove patch
@@ -33,74 +33,74 @@
 block discarded – undo
33 33
 use OCP\Settings\IDelegatedSettings;
34 34
 
35 35
 class Mail implements IDelegatedSettings {
36
-	/** @var IConfig */
37
-	private $config;
36
+    /** @var IConfig */
37
+    private $config;
38 38
 
39
-	/** @var IL10N $l */
40
-	private $l;
39
+    /** @var IL10N $l */
40
+    private $l;
41 41
 
42
-	/**
43
-	 * @param IConfig $config
44
-	 * @param IL10N $l
45
-	 */
46
-	public function __construct(IConfig $config, IL10N $l) {
47
-		$this->config = $config;
48
-		$this->l = $l;
49
-	}
42
+    /**
43
+     * @param IConfig $config
44
+     * @param IL10N $l
45
+     */
46
+    public function __construct(IConfig $config, IL10N $l) {
47
+        $this->config = $config;
48
+        $this->l = $l;
49
+    }
50 50
 
51
-	/**
52
-	 * @return TemplateResponse
53
-	 */
54
-	public function getForm() {
55
-		$parameters = [
56
-			// Mail
57
-			'sendmail_is_available' => (bool) \OC_Helper::findBinaryPath('sendmail'),
58
-			'mail_domain' => $this->config->getSystemValue('mail_domain', ''),
59
-			'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''),
60
-			'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''),
61
-			'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''),
62
-			'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''),
63
-			'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''),
64
-			'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false),
65
-			'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''),
66
-			'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''),
67
-			'mail_sendmailmode' => $this->config->getSystemValue('mail_sendmailmode', 'smtp'),
68
-		];
51
+    /**
52
+     * @return TemplateResponse
53
+     */
54
+    public function getForm() {
55
+        $parameters = [
56
+            // Mail
57
+            'sendmail_is_available' => (bool) \OC_Helper::findBinaryPath('sendmail'),
58
+            'mail_domain' => $this->config->getSystemValue('mail_domain', ''),
59
+            'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''),
60
+            'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''),
61
+            'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''),
62
+            'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''),
63
+            'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''),
64
+            'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false),
65
+            'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''),
66
+            'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''),
67
+            'mail_sendmailmode' => $this->config->getSystemValue('mail_sendmailmode', 'smtp'),
68
+        ];
69 69
 
70
-		if ($parameters['mail_smtppassword'] !== '') {
71
-			$parameters['mail_smtppassword'] = '********';
72
-		}
70
+        if ($parameters['mail_smtppassword'] !== '') {
71
+            $parameters['mail_smtppassword'] = '********';
72
+        }
73 73
 
74
-		if ($parameters['mail_smtpmode'] === '' || $parameters['mail_smtpmode'] === 'php') {
75
-			$parameters['mail_smtpmode'] = 'smtp';
76
-		}
74
+        if ($parameters['mail_smtpmode'] === '' || $parameters['mail_smtpmode'] === 'php') {
75
+            $parameters['mail_smtpmode'] = 'smtp';
76
+        }
77 77
 
78
-		return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, '');
79
-	}
78
+        return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, '');
79
+    }
80 80
 
81
-	/**
82
-	 * @return string the section ID, e.g. 'sharing'
83
-	 */
84
-	public function getSection() {
85
-		return 'server';
86
-	}
81
+    /**
82
+     * @return string the section ID, e.g. 'sharing'
83
+     */
84
+    public function getSection() {
85
+        return 'server';
86
+    }
87 87
 
88
-	/**
89
-	 * @return int whether the form should be rather on the top or bottom of
90
-	 * the admin section. The forms are arranged in ascending order of the
91
-	 * priority values. It is required to return a value between 0 and 100.
92
-	 *
93
-	 * E.g.: 70
94
-	 */
95
-	public function getPriority() {
96
-		return 10;
97
-	}
88
+    /**
89
+     * @return int whether the form should be rather on the top or bottom of
90
+     * the admin section. The forms are arranged in ascending order of the
91
+     * priority values. It is required to return a value between 0 and 100.
92
+     *
93
+     * E.g.: 70
94
+     */
95
+    public function getPriority() {
96
+        return 10;
97
+    }
98 98
 
99
-	public function getName(): ?string {
100
-		return $this->l->t('Email server');
101
-	}
99
+    public function getName(): ?string {
100
+        return $this->l->t('Email server');
101
+    }
102 102
 
103
-	public function getAuthorizedAppConfig(): array {
104
-		return [];
105
-	}
103
+    public function getAuthorizedAppConfig(): array {
104
+        return [];
105
+    }
106 106
 }
Please login to merge, or discard this patch.
apps/settings/lib/Controller/MailSettingsController.php 1 patch
Indentation   +143 added lines, -143 removed lines patch added patch discarded remove patch
@@ -39,147 +39,147 @@
 block discarded – undo
39 39
 
40 40
 class MailSettingsController extends Controller {
41 41
 
42
-	/** @var IL10N */
43
-	private $l10n;
44
-	/** @var IConfig */
45
-	private $config;
46
-	/** @var IUserSession */
47
-	private $userSession;
48
-	/** @var IMailer */
49
-	private $mailer;
50
-	/** @var IURLGenerator */
51
-	private $urlGenerator;
52
-
53
-	/**
54
-	 * @param string $appName
55
-	 * @param IRequest $request
56
-	 * @param IL10N $l10n
57
-	 * @param IConfig $config
58
-	 * @param IUserSession $userSession
59
-	 * @param IURLGenerator $urlGenerator,
60
-	 * @param IMailer $mailer
61
-	 */
62
-	public function __construct($appName,
63
-								IRequest $request,
64
-								IL10N $l10n,
65
-								IConfig $config,
66
-								IUserSession $userSession,
67
-								IURLGenerator $urlGenerator,
68
-								IMailer $mailer) {
69
-		parent::__construct($appName, $request);
70
-		$this->l10n = $l10n;
71
-		$this->config = $config;
72
-		$this->userSession = $userSession;
73
-		$this->urlGenerator = $urlGenerator;
74
-		$this->mailer = $mailer;
75
-	}
76
-
77
-	/**
78
-	 * Sets the email settings
79
-	 *
80
-	 * @PasswordConfirmationRequired
81
-	 * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Overview)
82
-	 *
83
-	 * @param string $mail_domain
84
-	 * @param string $mail_from_address
85
-	 * @param string $mail_smtpmode
86
-	 * @param string $mail_smtpsecure
87
-	 * @param string $mail_smtphost
88
-	 * @param int $mail_smtpauth
89
-	 * @param string $mail_smtpport
90
-	 * @return DataResponse
91
-	 */
92
-	public function setMailSettings($mail_domain,
93
-									$mail_from_address,
94
-									$mail_smtpmode,
95
-									$mail_smtpsecure,
96
-									$mail_smtphost,
97
-									$mail_smtpauth,
98
-									$mail_smtpport,
99
-									$mail_sendmailmode) {
100
-		$params = get_defined_vars();
101
-		$configs = [];
102
-		foreach ($params as $key => $value) {
103
-			$configs[$key] = empty($value) ? null : $value;
104
-		}
105
-
106
-		// Delete passwords from config in case no auth is specified
107
-		if ($params['mail_smtpauth'] !== 1) {
108
-			$configs['mail_smtpname'] = null;
109
-			$configs['mail_smtppassword'] = null;
110
-		}
111
-
112
-		$this->config->setSystemValues($configs);
113
-
114
-		$this->config->setAppValue('core', 'emailTestSuccessful', '0');
115
-
116
-		return new DataResponse();
117
-	}
118
-
119
-	/**
120
-	 * Store the credentials used for SMTP in the config
121
-	 *
122
-	 * @PasswordConfirmationRequired
123
-	 * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Overview)
124
-	 *
125
-	 * @param string $mail_smtpname
126
-	 * @param string $mail_smtppassword
127
-	 * @return DataResponse
128
-	 */
129
-	public function storeCredentials($mail_smtpname, $mail_smtppassword) {
130
-		if ($mail_smtppassword === '********') {
131
-			return new DataResponse($this->l10n->t('Invalid SMTP password.'), Http::STATUS_BAD_REQUEST);
132
-		}
133
-
134
-		$this->config->setSystemValues([
135
-			'mail_smtpname' => $mail_smtpname,
136
-			'mail_smtppassword' => $mail_smtppassword,
137
-		]);
138
-
139
-		$this->config->setAppValue('core', 'emailTestSuccessful', '0');
140
-
141
-		return new DataResponse();
142
-	}
143
-
144
-	/**
145
-	 * Send a mail to test the settings
146
-	 * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Overview)
147
-	 * @return DataResponse
148
-	 */
149
-	public function sendTestMail() {
150
-		$email = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'email', '');
151
-		if (!empty($email)) {
152
-			try {
153
-				$displayName = $this->userSession->getUser()->getDisplayName();
154
-
155
-				$template = $this->mailer->createEMailTemplate('settings.TestEmail', [
156
-					'displayname' => $displayName,
157
-				]);
158
-
159
-				$template->setSubject($this->l10n->t('Email setting test'));
160
-				$template->addHeader();
161
-				$template->addHeading($this->l10n->t('Well done, %s!', [$displayName]));
162
-				$template->addBodyText($this->l10n->t('If you received this email, the email configuration seems to be correct.'));
163
-				$template->addFooter();
164
-
165
-				$message = $this->mailer->createMessage();
166
-				$message->setTo([$email => $displayName]);
167
-				$message->useTemplate($template);
168
-				$errors = $this->mailer->send($message);
169
-				if (!empty($errors)) {
170
-					$this->config->setAppValue('core', 'emailTestSuccessful', '0');
171
-					throw new \RuntimeException($this->l10n->t('Email could not be sent. Check your mail server log'));
172
-				}
173
-				// Store the successful config in the app config
174
-				$this->config->setAppValue('core', 'emailTestSuccessful', '1');
175
-				return new DataResponse();
176
-			} catch (\Exception $e) {
177
-				$this->config->setAppValue('core', 'emailTestSuccessful', '0');
178
-				return new DataResponse($this->l10n->t('A problem occurred while sending the email. Please revise your settings. (Error: %s)', [$e->getMessage()]), Http::STATUS_BAD_REQUEST);
179
-			}
180
-		}
181
-
182
-		$this->config->setAppValue('core', 'emailTestSuccessful', '0');
183
-		return new DataResponse($this->l10n->t('You need to set your user email before being able to send test emails. Go to %s for that.', [$this->urlGenerator->linkToRouteAbsolute('settings.PersonalSettings.index')]), Http::STATUS_BAD_REQUEST);
184
-	}
42
+    /** @var IL10N */
43
+    private $l10n;
44
+    /** @var IConfig */
45
+    private $config;
46
+    /** @var IUserSession */
47
+    private $userSession;
48
+    /** @var IMailer */
49
+    private $mailer;
50
+    /** @var IURLGenerator */
51
+    private $urlGenerator;
52
+
53
+    /**
54
+     * @param string $appName
55
+     * @param IRequest $request
56
+     * @param IL10N $l10n
57
+     * @param IConfig $config
58
+     * @param IUserSession $userSession
59
+     * @param IURLGenerator $urlGenerator,
60
+     * @param IMailer $mailer
61
+     */
62
+    public function __construct($appName,
63
+                                IRequest $request,
64
+                                IL10N $l10n,
65
+                                IConfig $config,
66
+                                IUserSession $userSession,
67
+                                IURLGenerator $urlGenerator,
68
+                                IMailer $mailer) {
69
+        parent::__construct($appName, $request);
70
+        $this->l10n = $l10n;
71
+        $this->config = $config;
72
+        $this->userSession = $userSession;
73
+        $this->urlGenerator = $urlGenerator;
74
+        $this->mailer = $mailer;
75
+    }
76
+
77
+    /**
78
+     * Sets the email settings
79
+     *
80
+     * @PasswordConfirmationRequired
81
+     * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Overview)
82
+     *
83
+     * @param string $mail_domain
84
+     * @param string $mail_from_address
85
+     * @param string $mail_smtpmode
86
+     * @param string $mail_smtpsecure
87
+     * @param string $mail_smtphost
88
+     * @param int $mail_smtpauth
89
+     * @param string $mail_smtpport
90
+     * @return DataResponse
91
+     */
92
+    public function setMailSettings($mail_domain,
93
+                                    $mail_from_address,
94
+                                    $mail_smtpmode,
95
+                                    $mail_smtpsecure,
96
+                                    $mail_smtphost,
97
+                                    $mail_smtpauth,
98
+                                    $mail_smtpport,
99
+                                    $mail_sendmailmode) {
100
+        $params = get_defined_vars();
101
+        $configs = [];
102
+        foreach ($params as $key => $value) {
103
+            $configs[$key] = empty($value) ? null : $value;
104
+        }
105
+
106
+        // Delete passwords from config in case no auth is specified
107
+        if ($params['mail_smtpauth'] !== 1) {
108
+            $configs['mail_smtpname'] = null;
109
+            $configs['mail_smtppassword'] = null;
110
+        }
111
+
112
+        $this->config->setSystemValues($configs);
113
+
114
+        $this->config->setAppValue('core', 'emailTestSuccessful', '0');
115
+
116
+        return new DataResponse();
117
+    }
118
+
119
+    /**
120
+     * Store the credentials used for SMTP in the config
121
+     *
122
+     * @PasswordConfirmationRequired
123
+     * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Overview)
124
+     *
125
+     * @param string $mail_smtpname
126
+     * @param string $mail_smtppassword
127
+     * @return DataResponse
128
+     */
129
+    public function storeCredentials($mail_smtpname, $mail_smtppassword) {
130
+        if ($mail_smtppassword === '********') {
131
+            return new DataResponse($this->l10n->t('Invalid SMTP password.'), Http::STATUS_BAD_REQUEST);
132
+        }
133
+
134
+        $this->config->setSystemValues([
135
+            'mail_smtpname' => $mail_smtpname,
136
+            'mail_smtppassword' => $mail_smtppassword,
137
+        ]);
138
+
139
+        $this->config->setAppValue('core', 'emailTestSuccessful', '0');
140
+
141
+        return new DataResponse();
142
+    }
143
+
144
+    /**
145
+     * Send a mail to test the settings
146
+     * @AuthorizedAdminSetting(settings=OCA\Settings\Settings\Admin\Overview)
147
+     * @return DataResponse
148
+     */
149
+    public function sendTestMail() {
150
+        $email = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'email', '');
151
+        if (!empty($email)) {
152
+            try {
153
+                $displayName = $this->userSession->getUser()->getDisplayName();
154
+
155
+                $template = $this->mailer->createEMailTemplate('settings.TestEmail', [
156
+                    'displayname' => $displayName,
157
+                ]);
158
+
159
+                $template->setSubject($this->l10n->t('Email setting test'));
160
+                $template->addHeader();
161
+                $template->addHeading($this->l10n->t('Well done, %s!', [$displayName]));
162
+                $template->addBodyText($this->l10n->t('If you received this email, the email configuration seems to be correct.'));
163
+                $template->addFooter();
164
+
165
+                $message = $this->mailer->createMessage();
166
+                $message->setTo([$email => $displayName]);
167
+                $message->useTemplate($template);
168
+                $errors = $this->mailer->send($message);
169
+                if (!empty($errors)) {
170
+                    $this->config->setAppValue('core', 'emailTestSuccessful', '0');
171
+                    throw new \RuntimeException($this->l10n->t('Email could not be sent. Check your mail server log'));
172
+                }
173
+                // Store the successful config in the app config
174
+                $this->config->setAppValue('core', 'emailTestSuccessful', '1');
175
+                return new DataResponse();
176
+            } catch (\Exception $e) {
177
+                $this->config->setAppValue('core', 'emailTestSuccessful', '0');
178
+                return new DataResponse($this->l10n->t('A problem occurred while sending the email. Please revise your settings. (Error: %s)', [$e->getMessage()]), Http::STATUS_BAD_REQUEST);
179
+            }
180
+        }
181
+
182
+        $this->config->setAppValue('core', 'emailTestSuccessful', '0');
183
+        return new DataResponse($this->l10n->t('You need to set your user email before being able to send test emails. Go to %s for that.', [$this->urlGenerator->linkToRouteAbsolute('settings.PersonalSettings.index')]), Http::STATUS_BAD_REQUEST);
184
+    }
185 185
 }
Please login to merge, or discard this patch.
lib/public/Mail/IMailer.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -47,58 +47,58 @@
 block discarded – undo
47 47
  * @since 8.1.0
48 48
  */
49 49
 interface IMailer {
50
-	/**
51
-	 * Creates a new message object that can be passed to send()
52
-	 *
53
-	 * @return IMessage
54
-	 * @since 8.1.0
55
-	 */
56
-	public function createMessage(): IMessage;
50
+    /**
51
+     * Creates a new message object that can be passed to send()
52
+     *
53
+     * @return IMessage
54
+     * @since 8.1.0
55
+     */
56
+    public function createMessage(): IMessage;
57 57
 
58
-	/**
59
-	 * @param string|null $data
60
-	 * @param string|null $filename
61
-	 * @param string|null $contentType
62
-	 * @return IAttachment
63
-	 * @since 13.0.0
64
-	 */
65
-	public function createAttachment($data = null, $filename = null, $contentType = null): IAttachment;
58
+    /**
59
+     * @param string|null $data
60
+     * @param string|null $filename
61
+     * @param string|null $contentType
62
+     * @return IAttachment
63
+     * @since 13.0.0
64
+     */
65
+    public function createAttachment($data = null, $filename = null, $contentType = null): IAttachment;
66 66
 
67
-	/**
68
-	 * @param string $path
69
-	 * @param string|null $contentType
70
-	 * @return IAttachment
71
-	 * @since 13.0.0
72
-	 */
73
-	public function createAttachmentFromPath(string $path, $contentType = null): IAttachment;
67
+    /**
68
+     * @param string $path
69
+     * @param string|null $contentType
70
+     * @return IAttachment
71
+     * @since 13.0.0
72
+     */
73
+    public function createAttachmentFromPath(string $path, $contentType = null): IAttachment;
74 74
 
75
-	/**
76
-	 * Creates a new email template object
77
-	 *
78
-	 * @param string $emailId
79
-	 * @param array $data
80
-	 * @return IEMailTemplate
81
-	 * @since 12.0.0 Parameters added in 12.0.3
82
-	 */
83
-	public function createEMailTemplate(string $emailId, array $data = []): IEMailTemplate;
75
+    /**
76
+     * Creates a new email template object
77
+     *
78
+     * @param string $emailId
79
+     * @param array $data
80
+     * @return IEMailTemplate
81
+     * @since 12.0.0 Parameters added in 12.0.3
82
+     */
83
+    public function createEMailTemplate(string $emailId, array $data = []): IEMailTemplate;
84 84
 
85
-	/**
86
-	 * Send the specified message. Also sets the from address to the value defined in config.php
87
-	 * if no-one has been passed.
88
-	 *
89
-	 * @param IMessage $message Message to send
90
-	 * @return string[] Array with failed recipients. Be aware that this depends on the used mail backend and
91
-	 * therefore should be considered
92
-	 * @throws \Exception In case it was not possible to send the message. (for example if an invalid mail address
93
-	 * has been supplied.)
94
-	 * @since 8.1.0
95
-	 */
96
-	public function send(IMessage $message): array;
85
+    /**
86
+     * Send the specified message. Also sets the from address to the value defined in config.php
87
+     * if no-one has been passed.
88
+     *
89
+     * @param IMessage $message Message to send
90
+     * @return string[] Array with failed recipients. Be aware that this depends on the used mail backend and
91
+     * therefore should be considered
92
+     * @throws \Exception In case it was not possible to send the message. (for example if an invalid mail address
93
+     * has been supplied.)
94
+     * @since 8.1.0
95
+     */
96
+    public function send(IMessage $message): array;
97 97
 
98
-	/**
99
-	 * @param string $email Email address to be validated
100
-	 * @return bool True if the mail address is valid, false otherwise
101
-	 * @since 8.1.0
102
-	 */
103
-	public function validateMailAddress(string $email): bool;
98
+    /**
99
+     * @param string $email Email address to be validated
100
+     * @return bool True if the mail address is valid, false otherwise
101
+     * @since 8.1.0
102
+     */
103
+    public function validateMailAddress(string $email): bool;
104 104
 }
Please login to merge, or discard this patch.
lib/private/Mail/Attachment.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -36,58 +36,58 @@
 block discarded – undo
36 36
  * @since 13.0.0
37 37
  */
38 38
 class Attachment implements IAttachment {
39
-	private ?string $body;
40
-	private ?string $name;
41
-	private ?string $contentType;
42
-	private ?string $path;
39
+    private ?string $body;
40
+    private ?string $name;
41
+    private ?string $contentType;
42
+    private ?string $path;
43 43
 
44
-	public function __construct(
45
-		?string $body,
46
-		?string $name,
47
-		?string $contentType,
48
-		?string $path = null
49
-	) {
50
-		$this->body = $body;
51
-		$this->name = $name;
52
-		$this->contentType = $contentType;
53
-		$this->path = $path;
54
-	}
44
+    public function __construct(
45
+        ?string $body,
46
+        ?string $name,
47
+        ?string $contentType,
48
+        ?string $path = null
49
+    ) {
50
+        $this->body = $body;
51
+        $this->name = $name;
52
+        $this->contentType = $contentType;
53
+        $this->path = $path;
54
+    }
55 55
 
56
-	/**
57
-	 * @param string $filename
58
-	 * @return $this
59
-	 * @since 13.0.0
60
-	 */
61
-	public function setFilename(string $filename): IAttachment {
62
-		$this->name = $filename;
63
-		return $this;
64
-	}
56
+    /**
57
+     * @param string $filename
58
+     * @return $this
59
+     * @since 13.0.0
60
+     */
61
+    public function setFilename(string $filename): IAttachment {
62
+        $this->name = $filename;
63
+        return $this;
64
+    }
65 65
 
66
-	/**
67
-	 * @param string $contentType
68
-	 * @return $this
69
-	 * @since 13.0.0
70
-	 */
71
-	public function setContentType(string $contentType): IAttachment {
72
-		$this->contentType = $contentType;
73
-		return $this;
74
-	}
66
+    /**
67
+     * @param string $contentType
68
+     * @return $this
69
+     * @since 13.0.0
70
+     */
71
+    public function setContentType(string $contentType): IAttachment {
72
+        $this->contentType = $contentType;
73
+        return $this;
74
+    }
75 75
 
76
-	/**
77
-	 * @param string $body
78
-	 * @return $this
79
-	 * @since 13.0.0
80
-	 */
81
-	public function setBody(string $body): IAttachment {
82
-		$this->body = $body;
83
-		return $this;
84
-	}
76
+    /**
77
+     * @param string $body
78
+     * @return $this
79
+     * @since 13.0.0
80
+     */
81
+    public function setBody(string $body): IAttachment {
82
+        $this->body = $body;
83
+        return $this;
84
+    }
85 85
 
86
-	public function attach(Email $symfonyEmail): void {
87
-		if ($this->path !== null) {
88
-			$symfonyEmail->attachFromPath($this->path, $this->name, $this->contentType);
89
-		} else {
90
-			$symfonyEmail->attach($this->body, $this->name, $this->contentType);
91
-		}
92
-	}
86
+    public function attach(Email $symfonyEmail): void {
87
+        if ($this->path !== null) {
88
+            $symfonyEmail->attachFromPath($this->path, $this->name, $this->contentType);
89
+        } else {
90
+            $symfonyEmail->attach($this->body, $this->name, $this->contentType);
91
+        }
92
+    }
93 93
 }
Please login to merge, or discard this patch.
lib/private/Mail/Mailer.php 2 patches
Indentation   +283 added lines, -283 removed lines patch added patch discarded remove patch
@@ -79,287 +79,287 @@
 block discarded – undo
79 79
  * @package OC\Mail
80 80
  */
81 81
 class Mailer implements IMailer {
82
-	private ?MailerInterface $instance = null;
83
-	private IConfig $config;
84
-	private LoggerInterface $logger;
85
-	private Defaults $defaults;
86
-	private IURLGenerator $urlGenerator;
87
-	private IL10N $l10n;
88
-	private IEventDispatcher $dispatcher;
89
-	private IFactory $l10nFactory;
90
-
91
-	public function __construct(IConfig $config,
92
-						 LoggerInterface $logger,
93
-						 Defaults $defaults,
94
-						 IURLGenerator $urlGenerator,
95
-						 IL10N $l10n,
96
-						 IEventDispatcher $dispatcher,
97
-						 IFactory $l10nFactory) {
98
-		$this->config = $config;
99
-		$this->logger = $logger;
100
-		$this->defaults = $defaults;
101
-		$this->urlGenerator = $urlGenerator;
102
-		$this->l10n = $l10n;
103
-		$this->dispatcher = $dispatcher;
104
-		$this->l10nFactory = $l10nFactory;
105
-	}
106
-
107
-	/**
108
-	 * Creates a new message object that can be passed to send()
109
-	 *
110
-	 * @return Message
111
-	 */
112
-	public function createMessage(): Message {
113
-		$plainTextOnly = $this->config->getSystemValue('mail_send_plaintext_only', false);
114
-		return new Message(new Email(), $plainTextOnly);
115
-	}
116
-
117
-	/**
118
-	 * @param string|null $data
119
-	 * @param string|null $filename
120
-	 * @param string|null $contentType
121
-	 * @return IAttachment
122
-	 * @since 13.0.0
123
-	 */
124
-	public function createAttachment($data = null, $filename = null, $contentType = null): IAttachment {
125
-		return new Attachment($data, $filename, $contentType);
126
-	}
127
-
128
-	/**
129
-	 * @param string $path
130
-	 * @param string|null $contentType
131
-	 * @return IAttachment
132
-	 * @since 13.0.0
133
-	 */
134
-	public function createAttachmentFromPath(string $path, $contentType = null): IAttachment {
135
-		return new Attachment(null, null, $contentType, $path);
136
-	}
137
-
138
-	/**
139
-	 * Creates a new email template object
140
-	 *
141
-	 * @param string $emailId
142
-	 * @param array $data
143
-	 * @return IEMailTemplate
144
-	 * @since 12.0.0
145
-	 */
146
-	public function createEMailTemplate(string $emailId, array $data = []): IEMailTemplate {
147
-		$class = $this->config->getSystemValue('mail_template_class', '');
148
-
149
-		if ($class !== '' && class_exists($class) && is_a($class, EMailTemplate::class, true)) {
150
-			return new $class(
151
-				$this->defaults,
152
-				$this->urlGenerator,
153
-				$this->l10nFactory,
154
-				$emailId,
155
-				$data
156
-			);
157
-		}
158
-
159
-		return new EMailTemplate(
160
-			$this->defaults,
161
-			$this->urlGenerator,
162
-			$this->l10nFactory,
163
-			$emailId,
164
-			$data
165
-		);
166
-	}
167
-
168
-	/**
169
-	 * Send the specified message. Also sets the from address to the value defined in config.php
170
-	 * if no-one has been passed.
171
-	 *
172
-	 * If sending failed, the recipients that failed will be returned (to, cc and bcc).
173
-	 * Will output additional debug info if 'mail_smtpdebug' => 'true' is set in config.php
174
-	 *
175
-	 * @param IMessage $message Message to send
176
-	 * @return string[] $failedRecipients
177
-	 */
178
-	public function send(IMessage $message): array {
179
-		$debugMode = $this->config->getSystemValue('mail_smtpdebug', false);
180
-
181
-		if (!($message instanceof Message)) {
182
-			throw new InvalidArgumentException('Object not of type ' . Message::class);
183
-		}
184
-
185
-		if (empty($message->getFrom())) {
186
-			$message->setFrom([\OCP\Util::getDefaultEmailAddress('no-reply') => $this->defaults->getName()]);
187
-		}
188
-
189
-		$mailer = $this->getInstance();
190
-
191
-		$this->dispatcher->dispatchTyped(new BeforeMessageSent($message));
192
-
193
-		try {
194
-			$message->setRecipients();
195
-		} catch (InvalidArgumentException|RfcComplianceException $e) {
196
-			$logMessage = sprintf(
197
-				'Could not send mail to "%s" with subject "%s" as validation for address failed',
198
-				print_r(array_merge($message->getTo(), $message->getCc(), $message->getBcc()), true),
199
-				$message->getSubject()
200
-			);
201
-			$this->logger->debug($logMessage, ['app' => 'core', 'exception' => $e]);
202
-			$recipients = array_merge($message->getTo(), $message->getCc(), $message->getBcc());
203
-			$failedRecipients = [];
204
-
205
-			array_walk($recipients, function ($value, $key) use (&$failedRecipients) {
206
-				if (is_numeric($key)) {
207
-					$failedRecipients[] = $value;
208
-				} else {
209
-					$failedRecipients[] = $key;
210
-				}
211
-			});
212
-
213
-			return $failedRecipients;
214
-		}
215
-
216
-		try {
217
-			$mailer->send($message->getSymfonyEmail());
218
-		} catch (TransportExceptionInterface $e) {
219
-			$logMessage = sprintf('Sending mail to "%s" with subject "%s" failed', print_r($message->getTo(), true), $message->getSubject());
220
-			$this->logger->debug($logMessage, ['app' => 'core', 'exception' => $e]);
221
-			if ($debugMode) {
222
-				$this->logger->debug($e->getDebug(), ['app' => 'core']);
223
-			}
224
-			$recipients = array_merge($message->getTo(), $message->getCc(), $message->getBcc());
225
-			$failedRecipients = [];
226
-
227
-			array_walk($recipients, function ($value, $key) use (&$failedRecipients) {
228
-				if (is_numeric($key)) {
229
-					$failedRecipients[] = $value;
230
-				} else {
231
-					$failedRecipients[] = $key;
232
-				}
233
-			});
234
-
235
-			return $failedRecipients;
236
-		}
237
-
238
-		// Debugging logging
239
-		$logMessage = sprintf('Sent mail to "%s" with subject "%s"', print_r($message->getTo(), true), $message->getSubject());
240
-		$this->logger->debug($logMessage, ['app' => 'core']);
241
-
242
-		return [];
243
-	}
244
-
245
-	/**
246
-	 * @deprecated 26.0.0 Implicit validation is done in \OC\Mail\Message::setRecipients
247
-	 *                    via \Symfony\Component\Mime\Address::__construct
248
-	 *
249
-	 * @param string $email Email address to be validated
250
-	 * @return bool True if the mail address is valid, false otherwise
251
-	 */
252
-	public function validateMailAddress(string $email): bool {
253
-		if ($email === '') {
254
-			// Shortcut: empty addresses are never valid
255
-			return false;
256
-		}
257
-		$validator = new EmailValidator();
258
-		$validation = new RFCValidation();
259
-
260
-		return $validator->isValid($email, $validation);
261
-	}
262
-
263
-	protected function getInstance(): MailerInterface {
264
-		if (!is_null($this->instance)) {
265
-			return $this->instance;
266
-		}
267
-
268
-		$transport = null;
269
-
270
-		switch ($this->config->getSystemValue('mail_smtpmode', 'smtp')) {
271
-			case 'sendmail':
272
-				$transport = $this->getSendMailInstance();
273
-				break;
274
-			case 'smtp':
275
-			default:
276
-				$transport = $this->getSmtpInstance();
277
-				break;
278
-		}
279
-
280
-		return new SymfonyMailer($transport);
281
-	}
282
-
283
-	/**
284
-	 * Returns the SMTP transport
285
-	 *
286
-	 * Only supports ssl/tls
287
-	 * starttls is not enforcable with Symfony Mailer but might be available
288
-	 * via the automatic config (Symfony Mailer internal)
289
-	 *
290
-	 * @return EsmtpTransport
291
-	 */
292
-	protected function getSmtpInstance(): EsmtpTransport {
293
-		// either null or true - if nothing is passed, let the symfony mailer figure out the configuration by itself
294
-		$mailSmtpsecure = ($this->config->getSystemValue('mail_smtpsecure', null) === 'ssl') ? true : null;
295
-		$transport = new EsmtpTransport(
296
-			$this->config->getSystemValue('mail_smtphost', '127.0.0.1'),
297
-			(int)$this->config->getSystemValue('mail_smtpport', 25),
298
-			$mailSmtpsecure,
299
-			null,
300
-			$this->logger
301
-		);
302
-		/** @var SocketStream $stream */
303
-		$stream = $transport->getStream();
304
-		/** @psalm-suppress InternalMethod */
305
-		$stream->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
306
-
307
-		if ($this->config->getSystemValue('mail_smtpauth', false)) {
308
-			$transport->setUsername($this->config->getSystemValue('mail_smtpname', ''));
309
-			$transport->setPassword($this->config->getSystemValue('mail_smtppassword', ''));
310
-		}
311
-
312
-		$streamingOptions = $this->config->getSystemValue('mail_smtpstreamoptions', []);
313
-		if (is_array($streamingOptions) && !empty($streamingOptions)) {
314
-			/** @psalm-suppress InternalMethod */
315
-			$currentStreamingOptions = $stream->getStreamOptions();
316
-
317
-			$currentStreamingOptions = array_merge_recursive($currentStreamingOptions, $streamingOptions);
318
-
319
-			/** @psalm-suppress InternalMethod */
320
-			$stream->setStreamOptions($currentStreamingOptions);
321
-		}
322
-
323
-		$overwriteCliUrl = parse_url(
324
-			$this->config->getSystemValueString('overwrite.cli.url', ''),
325
-			PHP_URL_HOST
326
-		);
327
-
328
-		if (!empty($overwriteCliUrl)) {
329
-			$transport->setLocalDomain($overwriteCliUrl);
330
-		}
331
-
332
-		return $transport;
333
-	}
334
-
335
-	/**
336
-	 * Returns the sendmail transport
337
-	 *
338
-	 * @return SendmailTransport
339
-	 */
340
-	protected function getSendMailInstance(): SendmailTransport {
341
-		switch ($this->config->getSystemValue('mail_smtpmode', 'smtp')) {
342
-			case 'qmail':
343
-				$binaryPath = '/var/qmail/bin/sendmail';
344
-				break;
345
-			default:
346
-				$sendmail = \OCP\Server::get(IBinaryFinder::class)->findBinaryPath('sendmail');
347
-				if ($sendmail === null) {
348
-					$sendmail = '/usr/sbin/sendmail';
349
-				}
350
-				$binaryPath = $sendmail;
351
-				break;
352
-		}
353
-
354
-		switch ($this->config->getSystemValue('mail_sendmailmode', 'smtp')) {
355
-			case 'pipe':
356
-				$binaryParam = ' -t';
357
-				break;
358
-			default:
359
-				$binaryParam = ' -bs';
360
-				break;
361
-		}
362
-
363
-		return new SendmailTransport($binaryPath . $binaryParam, null, $this->logger);
364
-	}
82
+    private ?MailerInterface $instance = null;
83
+    private IConfig $config;
84
+    private LoggerInterface $logger;
85
+    private Defaults $defaults;
86
+    private IURLGenerator $urlGenerator;
87
+    private IL10N $l10n;
88
+    private IEventDispatcher $dispatcher;
89
+    private IFactory $l10nFactory;
90
+
91
+    public function __construct(IConfig $config,
92
+                            LoggerInterface $logger,
93
+                            Defaults $defaults,
94
+                            IURLGenerator $urlGenerator,
95
+                            IL10N $l10n,
96
+                            IEventDispatcher $dispatcher,
97
+                            IFactory $l10nFactory) {
98
+        $this->config = $config;
99
+        $this->logger = $logger;
100
+        $this->defaults = $defaults;
101
+        $this->urlGenerator = $urlGenerator;
102
+        $this->l10n = $l10n;
103
+        $this->dispatcher = $dispatcher;
104
+        $this->l10nFactory = $l10nFactory;
105
+    }
106
+
107
+    /**
108
+     * Creates a new message object that can be passed to send()
109
+     *
110
+     * @return Message
111
+     */
112
+    public function createMessage(): Message {
113
+        $plainTextOnly = $this->config->getSystemValue('mail_send_plaintext_only', false);
114
+        return new Message(new Email(), $plainTextOnly);
115
+    }
116
+
117
+    /**
118
+     * @param string|null $data
119
+     * @param string|null $filename
120
+     * @param string|null $contentType
121
+     * @return IAttachment
122
+     * @since 13.0.0
123
+     */
124
+    public function createAttachment($data = null, $filename = null, $contentType = null): IAttachment {
125
+        return new Attachment($data, $filename, $contentType);
126
+    }
127
+
128
+    /**
129
+     * @param string $path
130
+     * @param string|null $contentType
131
+     * @return IAttachment
132
+     * @since 13.0.0
133
+     */
134
+    public function createAttachmentFromPath(string $path, $contentType = null): IAttachment {
135
+        return new Attachment(null, null, $contentType, $path);
136
+    }
137
+
138
+    /**
139
+     * Creates a new email template object
140
+     *
141
+     * @param string $emailId
142
+     * @param array $data
143
+     * @return IEMailTemplate
144
+     * @since 12.0.0
145
+     */
146
+    public function createEMailTemplate(string $emailId, array $data = []): IEMailTemplate {
147
+        $class = $this->config->getSystemValue('mail_template_class', '');
148
+
149
+        if ($class !== '' && class_exists($class) && is_a($class, EMailTemplate::class, true)) {
150
+            return new $class(
151
+                $this->defaults,
152
+                $this->urlGenerator,
153
+                $this->l10nFactory,
154
+                $emailId,
155
+                $data
156
+            );
157
+        }
158
+
159
+        return new EMailTemplate(
160
+            $this->defaults,
161
+            $this->urlGenerator,
162
+            $this->l10nFactory,
163
+            $emailId,
164
+            $data
165
+        );
166
+    }
167
+
168
+    /**
169
+     * Send the specified message. Also sets the from address to the value defined in config.php
170
+     * if no-one has been passed.
171
+     *
172
+     * If sending failed, the recipients that failed will be returned (to, cc and bcc).
173
+     * Will output additional debug info if 'mail_smtpdebug' => 'true' is set in config.php
174
+     *
175
+     * @param IMessage $message Message to send
176
+     * @return string[] $failedRecipients
177
+     */
178
+    public function send(IMessage $message): array {
179
+        $debugMode = $this->config->getSystemValue('mail_smtpdebug', false);
180
+
181
+        if (!($message instanceof Message)) {
182
+            throw new InvalidArgumentException('Object not of type ' . Message::class);
183
+        }
184
+
185
+        if (empty($message->getFrom())) {
186
+            $message->setFrom([\OCP\Util::getDefaultEmailAddress('no-reply') => $this->defaults->getName()]);
187
+        }
188
+
189
+        $mailer = $this->getInstance();
190
+
191
+        $this->dispatcher->dispatchTyped(new BeforeMessageSent($message));
192
+
193
+        try {
194
+            $message->setRecipients();
195
+        } catch (InvalidArgumentException|RfcComplianceException $e) {
196
+            $logMessage = sprintf(
197
+                'Could not send mail to "%s" with subject "%s" as validation for address failed',
198
+                print_r(array_merge($message->getTo(), $message->getCc(), $message->getBcc()), true),
199
+                $message->getSubject()
200
+            );
201
+            $this->logger->debug($logMessage, ['app' => 'core', 'exception' => $e]);
202
+            $recipients = array_merge($message->getTo(), $message->getCc(), $message->getBcc());
203
+            $failedRecipients = [];
204
+
205
+            array_walk($recipients, function ($value, $key) use (&$failedRecipients) {
206
+                if (is_numeric($key)) {
207
+                    $failedRecipients[] = $value;
208
+                } else {
209
+                    $failedRecipients[] = $key;
210
+                }
211
+            });
212
+
213
+            return $failedRecipients;
214
+        }
215
+
216
+        try {
217
+            $mailer->send($message->getSymfonyEmail());
218
+        } catch (TransportExceptionInterface $e) {
219
+            $logMessage = sprintf('Sending mail to "%s" with subject "%s" failed', print_r($message->getTo(), true), $message->getSubject());
220
+            $this->logger->debug($logMessage, ['app' => 'core', 'exception' => $e]);
221
+            if ($debugMode) {
222
+                $this->logger->debug($e->getDebug(), ['app' => 'core']);
223
+            }
224
+            $recipients = array_merge($message->getTo(), $message->getCc(), $message->getBcc());
225
+            $failedRecipients = [];
226
+
227
+            array_walk($recipients, function ($value, $key) use (&$failedRecipients) {
228
+                if (is_numeric($key)) {
229
+                    $failedRecipients[] = $value;
230
+                } else {
231
+                    $failedRecipients[] = $key;
232
+                }
233
+            });
234
+
235
+            return $failedRecipients;
236
+        }
237
+
238
+        // Debugging logging
239
+        $logMessage = sprintf('Sent mail to "%s" with subject "%s"', print_r($message->getTo(), true), $message->getSubject());
240
+        $this->logger->debug($logMessage, ['app' => 'core']);
241
+
242
+        return [];
243
+    }
244
+
245
+    /**
246
+     * @deprecated 26.0.0 Implicit validation is done in \OC\Mail\Message::setRecipients
247
+     *                    via \Symfony\Component\Mime\Address::__construct
248
+     *
249
+     * @param string $email Email address to be validated
250
+     * @return bool True if the mail address is valid, false otherwise
251
+     */
252
+    public function validateMailAddress(string $email): bool {
253
+        if ($email === '') {
254
+            // Shortcut: empty addresses are never valid
255
+            return false;
256
+        }
257
+        $validator = new EmailValidator();
258
+        $validation = new RFCValidation();
259
+
260
+        return $validator->isValid($email, $validation);
261
+    }
262
+
263
+    protected function getInstance(): MailerInterface {
264
+        if (!is_null($this->instance)) {
265
+            return $this->instance;
266
+        }
267
+
268
+        $transport = null;
269
+
270
+        switch ($this->config->getSystemValue('mail_smtpmode', 'smtp')) {
271
+            case 'sendmail':
272
+                $transport = $this->getSendMailInstance();
273
+                break;
274
+            case 'smtp':
275
+            default:
276
+                $transport = $this->getSmtpInstance();
277
+                break;
278
+        }
279
+
280
+        return new SymfonyMailer($transport);
281
+    }
282
+
283
+    /**
284
+     * Returns the SMTP transport
285
+     *
286
+     * Only supports ssl/tls
287
+     * starttls is not enforcable with Symfony Mailer but might be available
288
+     * via the automatic config (Symfony Mailer internal)
289
+     *
290
+     * @return EsmtpTransport
291
+     */
292
+    protected function getSmtpInstance(): EsmtpTransport {
293
+        // either null or true - if nothing is passed, let the symfony mailer figure out the configuration by itself
294
+        $mailSmtpsecure = ($this->config->getSystemValue('mail_smtpsecure', null) === 'ssl') ? true : null;
295
+        $transport = new EsmtpTransport(
296
+            $this->config->getSystemValue('mail_smtphost', '127.0.0.1'),
297
+            (int)$this->config->getSystemValue('mail_smtpport', 25),
298
+            $mailSmtpsecure,
299
+            null,
300
+            $this->logger
301
+        );
302
+        /** @var SocketStream $stream */
303
+        $stream = $transport->getStream();
304
+        /** @psalm-suppress InternalMethod */
305
+        $stream->setTimeout($this->config->getSystemValue('mail_smtptimeout', 10));
306
+
307
+        if ($this->config->getSystemValue('mail_smtpauth', false)) {
308
+            $transport->setUsername($this->config->getSystemValue('mail_smtpname', ''));
309
+            $transport->setPassword($this->config->getSystemValue('mail_smtppassword', ''));
310
+        }
311
+
312
+        $streamingOptions = $this->config->getSystemValue('mail_smtpstreamoptions', []);
313
+        if (is_array($streamingOptions) && !empty($streamingOptions)) {
314
+            /** @psalm-suppress InternalMethod */
315
+            $currentStreamingOptions = $stream->getStreamOptions();
316
+
317
+            $currentStreamingOptions = array_merge_recursive($currentStreamingOptions, $streamingOptions);
318
+
319
+            /** @psalm-suppress InternalMethod */
320
+            $stream->setStreamOptions($currentStreamingOptions);
321
+        }
322
+
323
+        $overwriteCliUrl = parse_url(
324
+            $this->config->getSystemValueString('overwrite.cli.url', ''),
325
+            PHP_URL_HOST
326
+        );
327
+
328
+        if (!empty($overwriteCliUrl)) {
329
+            $transport->setLocalDomain($overwriteCliUrl);
330
+        }
331
+
332
+        return $transport;
333
+    }
334
+
335
+    /**
336
+     * Returns the sendmail transport
337
+     *
338
+     * @return SendmailTransport
339
+     */
340
+    protected function getSendMailInstance(): SendmailTransport {
341
+        switch ($this->config->getSystemValue('mail_smtpmode', 'smtp')) {
342
+            case 'qmail':
343
+                $binaryPath = '/var/qmail/bin/sendmail';
344
+                break;
345
+            default:
346
+                $sendmail = \OCP\Server::get(IBinaryFinder::class)->findBinaryPath('sendmail');
347
+                if ($sendmail === null) {
348
+                    $sendmail = '/usr/sbin/sendmail';
349
+                }
350
+                $binaryPath = $sendmail;
351
+                break;
352
+        }
353
+
354
+        switch ($this->config->getSystemValue('mail_sendmailmode', 'smtp')) {
355
+            case 'pipe':
356
+                $binaryParam = ' -t';
357
+                break;
358
+            default:
359
+                $binaryParam = ' -bs';
360
+                break;
361
+        }
362
+
363
+        return new SendmailTransport($binaryPath . $binaryParam, null, $this->logger);
364
+    }
365 365
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
 		$debugMode = $this->config->getSystemValue('mail_smtpdebug', false);
180 180
 
181 181
 		if (!($message instanceof Message)) {
182
-			throw new InvalidArgumentException('Object not of type ' . Message::class);
182
+			throw new InvalidArgumentException('Object not of type '.Message::class);
183 183
 		}
184 184
 
185 185
 		if (empty($message->getFrom())) {
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
 
193 193
 		try {
194 194
 			$message->setRecipients();
195
-		} catch (InvalidArgumentException|RfcComplianceException $e) {
195
+		} catch (InvalidArgumentException | RfcComplianceException $e) {
196 196
 			$logMessage = sprintf(
197 197
 				'Could not send mail to "%s" with subject "%s" as validation for address failed',
198 198
 				print_r(array_merge($message->getTo(), $message->getCc(), $message->getBcc()), true),
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
 			$recipients = array_merge($message->getTo(), $message->getCc(), $message->getBcc());
203 203
 			$failedRecipients = [];
204 204
 
205
-			array_walk($recipients, function ($value, $key) use (&$failedRecipients) {
205
+			array_walk($recipients, function($value, $key) use (&$failedRecipients) {
206 206
 				if (is_numeric($key)) {
207 207
 					$failedRecipients[] = $value;
208 208
 				} else {
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 			$recipients = array_merge($message->getTo(), $message->getCc(), $message->getBcc());
225 225
 			$failedRecipients = [];
226 226
 
227
-			array_walk($recipients, function ($value, $key) use (&$failedRecipients) {
227
+			array_walk($recipients, function($value, $key) use (&$failedRecipients) {
228 228
 				if (is_numeric($key)) {
229 229
 					$failedRecipients[] = $value;
230 230
 				} else {
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
 		$mailSmtpsecure = ($this->config->getSystemValue('mail_smtpsecure', null) === 'ssl') ? true : null;
295 295
 		$transport = new EsmtpTransport(
296 296
 			$this->config->getSystemValue('mail_smtphost', '127.0.0.1'),
297
-			(int)$this->config->getSystemValue('mail_smtpport', 25),
297
+			(int) $this->config->getSystemValue('mail_smtpport', 25),
298 298
 			$mailSmtpsecure,
299 299
 			null,
300 300
 			$this->logger
@@ -360,6 +360,6 @@  discard block
 block discarded – undo
360 360
 				break;
361 361
 		}
362 362
 
363
-		return new SendmailTransport($binaryPath . $binaryParam, null, $this->logger);
363
+		return new SendmailTransport($binaryPath.$binaryParam, null, $this->logger);
364 364
 	}
365 365
 }
Please login to merge, or discard this patch.
lib/private/Mail/Message.php 2 patches
Indentation   +295 added lines, -295 removed lines patch added patch discarded remove patch
@@ -46,299 +46,299 @@
 block discarded – undo
46 46
  * @package OC\Mail
47 47
  */
48 48
 class Message implements IMessage {
49
-	private Email $symfonyEmail;
50
-	private bool $plainTextOnly;
51
-
52
-	private array $to;
53
-	private array $from;
54
-	private array $replyTo;
55
-	private array $cc;
56
-	private array $bcc;
57
-
58
-	public function __construct(Email $symfonyEmail, bool $plainTextOnly) {
59
-		$this->symfonyEmail = $symfonyEmail;
60
-		$this->plainTextOnly = $plainTextOnly;
61
-		$this->to = [];
62
-		$this->from = [];
63
-		$this->replyTo = [];
64
-		$this->cc = [];
65
-		$this->bcc = [];
66
-	}
67
-
68
-	/**
69
-	 * @return $this
70
-	 * @since 13.0.0
71
-	 */
72
-	public function attach(IAttachment $attachment): IMessage {
73
-		/** @var Attachment $attachment */
74
-		$attachment->attach($this->symfonyEmail);
75
-		return $this;
76
-	}
77
-
78
-	/**
79
-	 * Converts the [['displayName' => 'email'], ['displayName2' => 'email2']] arrays to valid Adresses
80
-	 *
81
-	 * @param array $addresses Array of mail addresses
82
-	 * @return Address[]
83
-	 * @throws RfcComplianceException|InvalidArgumentException
84
-	 */
85
-	protected function convertAddresses(array $addresses): array {
86
-		$convertedAddresses = [];
87
-
88
-		if (empty($addresses)) {
89
-			return [];
90
-		}
91
-
92
-		array_walk($addresses, function ($readableName, $email) use (&$convertedAddresses) {
93
-			if (is_numeric($email)) {
94
-				$convertedAddresses[] = new Address($readableName);
95
-			} else {
96
-				$convertedAddresses[] = new Address($email, $readableName);
97
-			}
98
-		});
99
-
100
-		return $convertedAddresses;
101
-	}
102
-
103
-	/**
104
-	 * Set the from address of this message.
105
-	 *
106
-	 * If no "From" address is used \OC\Mail\Mailer will use mail_from_address and mail_domain from config.php
107
-	 *
108
-	 * @param array $addresses Example: array('[email protected]', '[email protected]' => 'A name')
109
-	 * @return $this
110
-	 */
111
-	public function setFrom(array $addresses): IMessage {
112
-		$this->from = $addresses;
113
-		return $this;
114
-	}
115
-
116
-	/**
117
-	 * Get the from address of this message.
118
-	 */
119
-	public function getFrom(): array {
120
-		return $this->from;
121
-	}
122
-
123
-	/**
124
-	 * Set the Reply-To address of this message
125
-	 *
126
-	 * @return $this
127
-	 */
128
-	public function setReplyTo(array $addresses): IMessage {
129
-		$this->replyTo = $addresses;
130
-		return $this;
131
-	}
132
-
133
-	/**
134
-	 * Returns the Reply-To address of this message
135
-	 */
136
-	public function getReplyTo(): array {
137
-		return $this->replyTo;
138
-	}
139
-
140
-	/**
141
-	 * Set the to addresses of this message.
142
-	 *
143
-	 * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
144
-	 * @return $this
145
-	 */
146
-	public function setTo(array $recipients): IMessage {
147
-		$this->to = $recipients;
148
-		return $this;
149
-	}
150
-
151
-	/**
152
-	 * Get the to address of this message.
153
-	 */
154
-	public function getTo(): array {
155
-		return $this->to;
156
-	}
157
-
158
-	/**
159
-	 * Set the CC recipients of this message.
160
-	 *
161
-	 * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
162
-	 * @return $this
163
-	 */
164
-	public function setCc(array $recipients): IMessage {
165
-		$this->cc = $recipients;
166
-		return $this;
167
-	}
168
-
169
-	/**
170
-	 * Get the cc address of this message.
171
-	 */
172
-	public function getCc(): array {
173
-		return $this->cc;
174
-	}
175
-
176
-	/**
177
-	 * Set the BCC recipients of this message.
178
-	 *
179
-	 * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
180
-	 * @return $this
181
-	 */
182
-	public function setBcc(array $recipients): IMessage {
183
-		$this->bcc = $recipients;
184
-		return $this;
185
-	}
186
-
187
-	/**
188
-	 * Get the Bcc address of this message.
189
-	 */
190
-	public function getBcc(): array {
191
-		return $this->bcc;
192
-	}
193
-
194
-	/**
195
-	 * Set the subject of this message.
196
-	 *
197
-	 * @return $this
198
-	 */
199
-	public function setSubject(string $subject): IMessage {
200
-		$this->symfonyEmail->subject($subject);
201
-		return $this;
202
-	}
203
-
204
-	/**
205
-	 * Get the from subject of this message.
206
-	 */
207
-	public function getSubject(): string {
208
-		return $this->symfonyEmail->getSubject() ?? '';
209
-	}
210
-
211
-	/**
212
-	 * Set the plain-text body of this message.
213
-	 * @return $this
214
-	 */
215
-	public function setPlainBody(string $body): IMessage {
216
-		$this->symfonyEmail->text($body);
217
-		return $this;
218
-	}
219
-
220
-	/**
221
-	 * Get the plain body of this message.
222
-	 */
223
-	public function getPlainBody(): string {
224
-		/** @var string $body */
225
-		$body = $this->symfonyEmail->getTextBody() ?? '';
226
-		return $body;
227
-	}
228
-
229
-	/**
230
-	 * Set the HTML body of this message. Consider also sending a plain-text body instead of only an HTML one.
231
-	 * @return $this
232
-	 */
233
-	public function setHtmlBody(string $body): IMessage {
234
-		if (!$this->plainTextOnly) {
235
-			$this->symfonyEmail->html($body);
236
-		}
237
-		return $this;
238
-	}
239
-
240
-	/**
241
-	 * Set the underlying Email intance
242
-	 */
243
-	public function setSymfonyEmail(Email $symfonyEmail): void {
244
-		$this->symfonyEmail = $symfonyEmail;
245
-	}
246
-
247
-	/**
248
-	 * Get the underlying Email instance
249
-	 */
250
-	public function getSymfonyEmail(): Email {
251
-		return $this->symfonyEmail;
252
-	}
253
-
254
-	/**
255
-	 * @return $this
256
-	 */
257
-	public function setBody(string $body, string $contentType): IMessage {
258
-		if (!$this->plainTextOnly || $contentType !== 'text/html') {
259
-			if ($contentType === 'text/html') {
260
-				$this->symfonyEmail->html($body);
261
-			} else {
262
-				$this->symfonyEmail->text($body);
263
-			}
264
-		}
265
-		return $this;
266
-	}
267
-
268
-	/**
269
-	 * Set the recipients on the symphony email
270
-	 *
271
-	 * Since
272
-	 *
273
-	 * setTo
274
-	 * setFrom
275
-	 * setReplyTo
276
-	 * setCc
277
-	 * setBcc
278
-	 *
279
-	 * could throw a \Symfony\Component\Mime\Exception\RfcComplianceException
280
-	 * or a \Symfony\Component\Mime\Exception\InvalidArgumentException
281
-	 * we wrap the calls here. We then have the validation errors all in one place and can
282
-	 * throw shortly before \OC\Mail\Mailer::send
283
-	 *
284
-	 * @return void
285
-	 * @throws InvalidArgumentException|RfcComplianceException
286
-	 */
287
-	public function setRecipients() {
288
-		$this->symfonyEmail->to(...$this->convertAddresses($this->getTo()));
289
-		$this->symfonyEmail->from(...$this->convertAddresses($this->getFrom()));
290
-		$this->symfonyEmail->replyTo(...$this->convertAddresses($this->getReplyTo()));
291
-		$this->symfonyEmail->cc(...$this->convertAddresses($this->getCc()));
292
-		$this->symfonyEmail->bcc(...$this->convertAddresses($this->getBcc()));
293
-	}
294
-
295
-	/**
296
-	 * @return $this
297
-	 */
298
-	public function useTemplate(IEMailTemplate $emailTemplate): IMessage {
299
-		$this->setSubject($emailTemplate->renderSubject());
300
-		$this->setPlainBody($emailTemplate->renderText());
301
-		if (!$this->plainTextOnly) {
302
-			$this->setHtmlBody($emailTemplate->renderHtml());
303
-		}
304
-		return $this;
305
-	}
306
-
307
-	/**
308
-	 * Add the Auto-Submitted header to the email, preventing most automated
309
-	 * responses to automated messages.
310
-	 *
311
-	 * @param AutoSubmitted::VALUE_* $value (one of AutoSubmitted::VALUE_NO, AutoSubmitted::VALUE_AUTO_GENERATED, AutoSubmitted::VALUE_AUTO_REPLIED)
312
-	 * @return $this
313
-	 */
314
-	public function setAutoSubmitted(string $value): IMessage {
315
-		$headers = $this->symfonyEmail->getHeaders();
316
-
317
-		if ($headers->has(AutoSubmitted::HEADER)) {
318
-			// if the header already exsists, remove it.
319
-			// the value can be modified with some implementations
320
-			// of the interface \Swift_Mime_Header, however the
321
-			// interface doesn't, and this makes the static-code
322
-			// analysis unhappy.
323
-			// @todo check if symfony mailer can modify the autosubmitted header
324
-			$headers->remove(AutoSubmitted::HEADER);
325
-		}
326
-
327
-		$headers->addTextHeader(AutoSubmitted::HEADER, $value);
328
-
329
-		return $this;
330
-	}
331
-
332
-	/**
333
-	 * Get the current value of the Auto-Submitted header. Defaults to "no"
334
-	 * which is equivalent to the header not existing at all
335
-	 *
336
-	 * @return string
337
-	 */
338
-	public function getAutoSubmitted(): string {
339
-		$headers = $this->symfonyEmail->getHeaders();
340
-
341
-		return $headers->has(AutoSubmitted::HEADER) ?
342
-			$headers->get(AutoSubmitted::HEADER)->getBodyAsString() : AutoSubmitted::VALUE_NO;
343
-	}
49
+    private Email $symfonyEmail;
50
+    private bool $plainTextOnly;
51
+
52
+    private array $to;
53
+    private array $from;
54
+    private array $replyTo;
55
+    private array $cc;
56
+    private array $bcc;
57
+
58
+    public function __construct(Email $symfonyEmail, bool $plainTextOnly) {
59
+        $this->symfonyEmail = $symfonyEmail;
60
+        $this->plainTextOnly = $plainTextOnly;
61
+        $this->to = [];
62
+        $this->from = [];
63
+        $this->replyTo = [];
64
+        $this->cc = [];
65
+        $this->bcc = [];
66
+    }
67
+
68
+    /**
69
+     * @return $this
70
+     * @since 13.0.0
71
+     */
72
+    public function attach(IAttachment $attachment): IMessage {
73
+        /** @var Attachment $attachment */
74
+        $attachment->attach($this->symfonyEmail);
75
+        return $this;
76
+    }
77
+
78
+    /**
79
+     * Converts the [['displayName' => 'email'], ['displayName2' => 'email2']] arrays to valid Adresses
80
+     *
81
+     * @param array $addresses Array of mail addresses
82
+     * @return Address[]
83
+     * @throws RfcComplianceException|InvalidArgumentException
84
+     */
85
+    protected function convertAddresses(array $addresses): array {
86
+        $convertedAddresses = [];
87
+
88
+        if (empty($addresses)) {
89
+            return [];
90
+        }
91
+
92
+        array_walk($addresses, function ($readableName, $email) use (&$convertedAddresses) {
93
+            if (is_numeric($email)) {
94
+                $convertedAddresses[] = new Address($readableName);
95
+            } else {
96
+                $convertedAddresses[] = new Address($email, $readableName);
97
+            }
98
+        });
99
+
100
+        return $convertedAddresses;
101
+    }
102
+
103
+    /**
104
+     * Set the from address of this message.
105
+     *
106
+     * If no "From" address is used \OC\Mail\Mailer will use mail_from_address and mail_domain from config.php
107
+     *
108
+     * @param array $addresses Example: array('[email protected]', '[email protected]' => 'A name')
109
+     * @return $this
110
+     */
111
+    public function setFrom(array $addresses): IMessage {
112
+        $this->from = $addresses;
113
+        return $this;
114
+    }
115
+
116
+    /**
117
+     * Get the from address of this message.
118
+     */
119
+    public function getFrom(): array {
120
+        return $this->from;
121
+    }
122
+
123
+    /**
124
+     * Set the Reply-To address of this message
125
+     *
126
+     * @return $this
127
+     */
128
+    public function setReplyTo(array $addresses): IMessage {
129
+        $this->replyTo = $addresses;
130
+        return $this;
131
+    }
132
+
133
+    /**
134
+     * Returns the Reply-To address of this message
135
+     */
136
+    public function getReplyTo(): array {
137
+        return $this->replyTo;
138
+    }
139
+
140
+    /**
141
+     * Set the to addresses of this message.
142
+     *
143
+     * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
144
+     * @return $this
145
+     */
146
+    public function setTo(array $recipients): IMessage {
147
+        $this->to = $recipients;
148
+        return $this;
149
+    }
150
+
151
+    /**
152
+     * Get the to address of this message.
153
+     */
154
+    public function getTo(): array {
155
+        return $this->to;
156
+    }
157
+
158
+    /**
159
+     * Set the CC recipients of this message.
160
+     *
161
+     * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
162
+     * @return $this
163
+     */
164
+    public function setCc(array $recipients): IMessage {
165
+        $this->cc = $recipients;
166
+        return $this;
167
+    }
168
+
169
+    /**
170
+     * Get the cc address of this message.
171
+     */
172
+    public function getCc(): array {
173
+        return $this->cc;
174
+    }
175
+
176
+    /**
177
+     * Set the BCC recipients of this message.
178
+     *
179
+     * @param array $recipients Example: array('[email protected]', '[email protected]' => 'A name')
180
+     * @return $this
181
+     */
182
+    public function setBcc(array $recipients): IMessage {
183
+        $this->bcc = $recipients;
184
+        return $this;
185
+    }
186
+
187
+    /**
188
+     * Get the Bcc address of this message.
189
+     */
190
+    public function getBcc(): array {
191
+        return $this->bcc;
192
+    }
193
+
194
+    /**
195
+     * Set the subject of this message.
196
+     *
197
+     * @return $this
198
+     */
199
+    public function setSubject(string $subject): IMessage {
200
+        $this->symfonyEmail->subject($subject);
201
+        return $this;
202
+    }
203
+
204
+    /**
205
+     * Get the from subject of this message.
206
+     */
207
+    public function getSubject(): string {
208
+        return $this->symfonyEmail->getSubject() ?? '';
209
+    }
210
+
211
+    /**
212
+     * Set the plain-text body of this message.
213
+     * @return $this
214
+     */
215
+    public function setPlainBody(string $body): IMessage {
216
+        $this->symfonyEmail->text($body);
217
+        return $this;
218
+    }
219
+
220
+    /**
221
+     * Get the plain body of this message.
222
+     */
223
+    public function getPlainBody(): string {
224
+        /** @var string $body */
225
+        $body = $this->symfonyEmail->getTextBody() ?? '';
226
+        return $body;
227
+    }
228
+
229
+    /**
230
+     * Set the HTML body of this message. Consider also sending a plain-text body instead of only an HTML one.
231
+     * @return $this
232
+     */
233
+    public function setHtmlBody(string $body): IMessage {
234
+        if (!$this->plainTextOnly) {
235
+            $this->symfonyEmail->html($body);
236
+        }
237
+        return $this;
238
+    }
239
+
240
+    /**
241
+     * Set the underlying Email intance
242
+     */
243
+    public function setSymfonyEmail(Email $symfonyEmail): void {
244
+        $this->symfonyEmail = $symfonyEmail;
245
+    }
246
+
247
+    /**
248
+     * Get the underlying Email instance
249
+     */
250
+    public function getSymfonyEmail(): Email {
251
+        return $this->symfonyEmail;
252
+    }
253
+
254
+    /**
255
+     * @return $this
256
+     */
257
+    public function setBody(string $body, string $contentType): IMessage {
258
+        if (!$this->plainTextOnly || $contentType !== 'text/html') {
259
+            if ($contentType === 'text/html') {
260
+                $this->symfonyEmail->html($body);
261
+            } else {
262
+                $this->symfonyEmail->text($body);
263
+            }
264
+        }
265
+        return $this;
266
+    }
267
+
268
+    /**
269
+     * Set the recipients on the symphony email
270
+     *
271
+     * Since
272
+     *
273
+     * setTo
274
+     * setFrom
275
+     * setReplyTo
276
+     * setCc
277
+     * setBcc
278
+     *
279
+     * could throw a \Symfony\Component\Mime\Exception\RfcComplianceException
280
+     * or a \Symfony\Component\Mime\Exception\InvalidArgumentException
281
+     * we wrap the calls here. We then have the validation errors all in one place and can
282
+     * throw shortly before \OC\Mail\Mailer::send
283
+     *
284
+     * @return void
285
+     * @throws InvalidArgumentException|RfcComplianceException
286
+     */
287
+    public function setRecipients() {
288
+        $this->symfonyEmail->to(...$this->convertAddresses($this->getTo()));
289
+        $this->symfonyEmail->from(...$this->convertAddresses($this->getFrom()));
290
+        $this->symfonyEmail->replyTo(...$this->convertAddresses($this->getReplyTo()));
291
+        $this->symfonyEmail->cc(...$this->convertAddresses($this->getCc()));
292
+        $this->symfonyEmail->bcc(...$this->convertAddresses($this->getBcc()));
293
+    }
294
+
295
+    /**
296
+     * @return $this
297
+     */
298
+    public function useTemplate(IEMailTemplate $emailTemplate): IMessage {
299
+        $this->setSubject($emailTemplate->renderSubject());
300
+        $this->setPlainBody($emailTemplate->renderText());
301
+        if (!$this->plainTextOnly) {
302
+            $this->setHtmlBody($emailTemplate->renderHtml());
303
+        }
304
+        return $this;
305
+    }
306
+
307
+    /**
308
+     * Add the Auto-Submitted header to the email, preventing most automated
309
+     * responses to automated messages.
310
+     *
311
+     * @param AutoSubmitted::VALUE_* $value (one of AutoSubmitted::VALUE_NO, AutoSubmitted::VALUE_AUTO_GENERATED, AutoSubmitted::VALUE_AUTO_REPLIED)
312
+     * @return $this
313
+     */
314
+    public function setAutoSubmitted(string $value): IMessage {
315
+        $headers = $this->symfonyEmail->getHeaders();
316
+
317
+        if ($headers->has(AutoSubmitted::HEADER)) {
318
+            // if the header already exsists, remove it.
319
+            // the value can be modified with some implementations
320
+            // of the interface \Swift_Mime_Header, however the
321
+            // interface doesn't, and this makes the static-code
322
+            // analysis unhappy.
323
+            // @todo check if symfony mailer can modify the autosubmitted header
324
+            $headers->remove(AutoSubmitted::HEADER);
325
+        }
326
+
327
+        $headers->addTextHeader(AutoSubmitted::HEADER, $value);
328
+
329
+        return $this;
330
+    }
331
+
332
+    /**
333
+     * Get the current value of the Auto-Submitted header. Defaults to "no"
334
+     * which is equivalent to the header not existing at all
335
+     *
336
+     * @return string
337
+     */
338
+    public function getAutoSubmitted(): string {
339
+        $headers = $this->symfonyEmail->getHeaders();
340
+
341
+        return $headers->has(AutoSubmitted::HEADER) ?
342
+            $headers->get(AutoSubmitted::HEADER)->getBodyAsString() : AutoSubmitted::VALUE_NO;
343
+    }
344 344
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@
 block discarded – undo
89 89
 			return [];
90 90
 		}
91 91
 
92
-		array_walk($addresses, function ($readableName, $email) use (&$convertedAddresses) {
92
+		array_walk($addresses, function($readableName, $email) use (&$convertedAddresses) {
93 93
 			if (is_numeric($email)) {
94 94
 				$convertedAddresses[] = new Address($readableName);
95 95
 			} else {
Please login to merge, or discard this patch.