MailTemplateService.php 15.6 KB
Newer Older
1
2
3
4
<?php

namespace SGalinski\SgMail\Service;

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/***************************************************************
 *  Copyright notice
 *
 *  (c) sgalinski Internet Services (https://www.sgalinski.de)
 *
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
 *  free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  The GNU General Public License can be found at
 *  http://www.gnu.org/copyleft/gpl.html.
 *
 *  This script is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/
28

29
use DateTime;
30
31
32
use SGalinski\SgMail\Domain\Model\Mail;
use SGalinski\SgMail\Domain\Model\Template;
use SGalinski\SgMail\Domain\Repository\MailRepository;
33
use SGalinski\SgMail\Domain\Repository\TemplateRepository;
34
35
use Swift_Attachment;
use Swift_OutputByteStream;
36
37
38
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
39
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
40
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
41
42
use TYPO3\CMS\Fluid\View\StandaloneView;

43
44
45
/**
 * MailTemplateService
 */
46
class MailTemplateService {
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
	/**
	 * @var string
	 */
	const MARKER_TYPE_STRING = 'String';

	/**
	 * @var string
	 */
	const MARKER_TYPE_DATE = 'Date';

	/**
	 * @var string
	 */
	const MARKER_TYPE_INTEGER = 'Integer';

63
	/**
64
	 * @var array $registerArray
65
	 */
66
	private static $registerArray = [];
67

68
	/**
69
	 * @var array $toAddresses
70
	 */
71
	private $toAddresses = [];
72
73

	/**
74
	 * @var string $fromAddress
75
	 */
76
	private $fromAddress;
77
78

	/**
79
	 * @var array $ccAddresses
80
	 */
81
	private $ccAddresses = [];
82
83

	/**
84
	 * @var string $replyToAddress
85
	 */
86
	private $replyToAddress;
87
88

	/**
89
	 * @var string $language
90
	 */
91
	private $language;
92
93

	/**
94
	 * @var boolean $ignoreMailQueue
95
	 */
96
	private $ignoreMailQueue = FALSE;
97
98
99
100
101
102
103

	/**
	 * @var \TYPO3\CMS\Core\Mail\MailMessage $mailMessage
	 */
	private $mailMessage;

	/**
104
	 * @var string $templateName
105
106
107
108
	 */
	private $templateName;

	/**
109
	 * @var string $extensionKey
110
111
112
113
	 */
	private $extensionKey;

	/**
114
	 * @var array $markers
115
	 */
116
	private $markers = [];
117

118
119
120
	/**
	 * holds the TypoScript configuration for sg_mail
	 *
121
	 * @var array $tsSettings
122
123
124
	 */
	private $tsSettings = [];

125
126
127
128
129
	/**
	 * @var array $bccAddresses
	 */
	private $bccAddresses = [];

130
131
132
133
134
	/**
	 * @var int
	 */
	private $priority = Mail::PRIORITY_LOWEST;

135
136
137
	/**
	 * @var \SGalinski\SgMail\Domain\Repository\TemplateRepository
	 */
138
139
140
141
142
143
	protected $templateRepository;

	/**
	 * @var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
	 */
	protected $persistenceManager;
144

145
146
147
148
149
	/**
	 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
	 */
	protected $objectManager;

150
151
152
153
154
	/**
	 * @var array
	 */
	private $attachments = [];

155
156
157
158
	/**
	 * MailTemplateService constructor.
	 */
	public function __construct() {
159
160
161
162
163
164
		/** @var ObjectManager objectManager */
		$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
		/** @var MailMessage mailMessage */
		$this->mailMessage = $this->objectManager->get(MailMessage::class);
		/** @var TypoScriptSettingsService $typoScriptSettingsService */
		$typoScriptSettingsService = $this->objectManager->get(TypoScriptSettingsService::class);
165
166
		$this->tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');
		$this->language = $this->tsSettings['templateDefaultLanguage'];
167
168
169
170
		/** @var TemplateRepository templateRepository */
		$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
		/** @var PersistenceManager persistenceManager */
		$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);
171
172
173

		$this->fromAddress = $this->tsSettings['mail']['default']['from'];
		$this->mailMessage->setFrom($this->fromAddress);
174
		$this->bccAddresses = GeneralUtility::trimExplode(',', $this->tsSettings['mail']['default']['bcc']);
175
176
177
178
179
180
181
182
183
184
185
186
187
188
		$this->ccAddresses = GeneralUtility::trimExplode(',', $this->tsSettings['mail']['default']['cc']);

		foreach ($this->bccAddresses as $index => $email) {
			if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
				unset($this->bccAddresses[$index]);
			}
		}

		foreach ($this->ccAddresses as $index => $email) {
			if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
				unset($this->ccAddresses[$index]);
			}
		}

189
		$this->mailMessage->setFrom($this->fromAddress);
190
		if (count($this->bccAddresses) > 0) {
191
192
193
			$this->mailMessage->setBcc($this->bccAddresses);
		}

194
		if (count($this->ccAddresses) > 0) {
195
196
			$this->mailMessage->setCc($this->ccAddresses);
		}
197
198
	}

Torsten Oppermann's avatar
Torsten Oppermann committed
199
	/**
Torsten Oppermann's avatar
Torsten Oppermann committed
200
	 * register a template with sg_mail
Fabian Galinski's avatar
Fabian Galinski committed
201
	 *
202
203
204
	 * description and subject can now be an array i.e. with elements such as 'en' => 'english description'
	 * or an translation string used in locallang.xml
	 *
205
	 * @param string $extension
Torsten Oppermann's avatar
Torsten Oppermann committed
206
207
	 * @param string $templateName
	 * @param string $templatePath
208
	 * @param mixed $description
209
	 * @param array $markers
210
	 * @param mixed $subject
Torsten Oppermann's avatar
Torsten Oppermann committed
211
	 */
212
	public static function registerTemplate(
213
		$extension, $templateName, $templatePath, $description, array $markers, $subject
214
	) {
215
		MailTemplateService::$registerArray[$extension][$templateName] = [
216
			'templatePath' => $templatePath,
217
			'description' => $description,
218
			'marker' => $markers,
219
			'extension' => $extension,
220
			'templateName' => $templateName,
221
			'subject' => $subject
222
223
		];
	}
224

225
226
227
228
229
230
231
232
233
	/**
	 * Return default markers for sg_mail
	 *
	 * @param string $translationKey
	 * @param array $marker
	 * @param string $extensionKey
	 * @return array
	 */
	public static function getDefaultTemplateMarker($translationKey, array $marker, $extensionKey = 'sg_mail') {
234
		$languagePath = 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang.xlf:' . $translationKey;
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

		// Need the key for translations
		if (trim($extensionKey) === '') {
			return [];
		}

		$generatedMarker = [];
		foreach ($marker as $markerName) {
			$generatedMarker[] = [
				'marker' => $markerName,
				'value' => $languagePath . '.example.' . $markerName,
				'description' => $languagePath . '.description.' . $markerName,
				'backend_translation_key' => $translationKey . '.example.' . $markerName,
				'extension_key' => $extensionKey
			];
		}

		return $generatedMarker;
	}

255
	/**
Torsten Oppermann's avatar
Torsten Oppermann committed
256
	 * Get all registered templates
Fabian Galinski's avatar
Fabian Galinski committed
257
	 *
258
	 * @return array
259
	 */
260
261
	public static function getRegisterArray() {
		return self::$registerArray;
262
	}
263

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	/**
	 * Sets the predefined values for this template, supplied by the Editor, if possible
	 * values for cc, bcc, replyTo, fromMail and fromName
	 *
	 * @param string $extensionKey
	 * @param string $templateName
	 * @param string $language
	 * @return bool
	 */
	public function loadPredefinedValuesForTemplate($extensionKey, $templateName, $language) {
		/** @var Template $template */
		$template = $this->templateRepository->findOneByTemplate(
			$this->extensionKey, $this->templateName, $this->language
		);

		if ($template !== NULL) {
			$this->setCcAddresses(explode(',', $template->getCc()));
			$this->setBccAddresses(explode(',', $template->getBcc()));
			$this->setReplyToAddress($template->getReplyTo());
			$this->setFromAddress($template->getFromMail(), $template->getFromName());
284
			return TRUE;
285
286
		}

287
		return FALSE;
288
289
	}

290
	/**
291
	 * Send the Email
292
	 *
Torsten Oppermann's avatar
Torsten Oppermann committed
293
	 * @param boolean $isPreview
294
	 * @return boolean email was sent or added to mail queue successfully?
295
	 */
296
	public function sendEmail($isPreview = FALSE) {
297
		/** @var Template $template */
298
		$template = $this->templateRepository->findOneByTemplate(
299
			$this->extensionKey, $this->templateName, $this->language
300
		);
301

302
303
304
305
306
		// if there is a template, prefer those values
		if ($template) {
			$this->loadTemplateValues($template);
		}

307
308
309
310
311
312
313
314
		// If there is no template for this language, use the default template
		if ($template === NULL) {
			$templatePath = self::$registerArray[$this->extensionKey][$this->templateName]['templatePath'];
			$templateFile = $templatePath . $this->language . '.template.html';
			if (file_exists($templateFile)) {
				$defaultTemplateContent = file_get_contents($templatePath . $this->language . '.template.html');
			} else {
				// no language found and no default template
Torsten Oppermann's avatar
Torsten Oppermann committed
315
				$this->setLanguage('en');
316
317
318
319
320
321
322
				// does an english default template exist ?
				if (file_exists($templatePath . $this->language . '.template.html')) {
					$this->sendEmail();
					return TRUE;
				}

				return FALSE;
323
			}
324
325
		}

Torsten Oppermann's avatar
Torsten Oppermann committed
326
327
328
329
		if ($isPreview) {
			$previewMarker = [];
			$markerArray = self::$registerArray[$this->extensionKey][$this->templateName]['marker'];
			foreach ($markerArray as $marker) {
330
331
332
333
334
335
336
				if ($marker['backend_translation_key']) {
					$previewMarker[$marker['marker']] = LocalizationUtility::translate(
						$marker['backend_translation_key'], $marker['extension_key']
					);
				} else {
					$previewMarker[$marker['marker']] = $marker['value'];
				}
Torsten Oppermann's avatar
Torsten Oppermann committed
337
			}
338
			$this->setIgnoreMailQueue(TRUE);
Torsten Oppermann's avatar
Torsten Oppermann committed
339
340
341
			$this->setMarkers($previewMarker);
		}

342
		/** @var StandaloneView $emailView */
343
		$emailView = $this->objectManager->get(StandaloneView::class);
344

345
346
		if (!isset($defaultTemplateContent)) {
			$emailView->setTemplateSource($template->getContent());
347
			$subject = $template->getSubject();
348
349
		} else {
			$emailView->setTemplateSource($defaultTemplateContent);
350
351
352
353
354
355
356
357
358
359

			$subject = self::$registerArray[$this->extensionKey][$this->templateName]['subject'];
			if (is_array($subject)) {
				$subject = self::$registerArray[$this->extensionKey][$this->templateName]['subject'][$this->language];
			} else {
				$subject = LocalizationUtility::translate(
					self::$registerArray[$this->extensionKey][$this->templateName]['subject'],
					$this->extensionKey
				);
			}
360
		}
361
		$this->mailMessage->setSubject($subject);
362

363
		$emailView->assignMultiple($this->markers);
364
		$emailBody = $emailView->render();
365

366
367
368
369
		// insert <br /> tags, but replace every instance of three or more successive breaks with just two.
		$emailBody = nl2br($emailBody);
		$emailBody = preg_replace('/(<br[\s]?[\/]?>[\s]*){3,}/', '<br /><br />', $emailBody);
		if ($this->ignoreMailQueue) {
370

371
			$this->mailMessage->setBody($emailBody, 'text/html');
372
			$this->mailMessage->send();
373
374
375
376
377
378
			$dateTime = new DateTime();
			$this->addMailToMailQueue(
				$this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority, $dateTime->getTimestamp(), TRUE
			);


379
		} else {
380
			$this->addMailToMailQueue($this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority);
381
		}
382
383

		return TRUE;
384
385
386
	}

	/**
387
	 * Adds a new mail to the mail queue.
388
	 *
389
390
	 * @param string $extensionKey
	 * @param string $templateName
391
	 * @param string $subject
392
	 * @param string $emailBody
393
	 * @param int $sendingTime
394
	 * @param int $priority
395
	 * @param bool $sent
396
	 */
397
	private function addMailToMailQueue($extensionKey, $templateName, $subject, $emailBody, $priority, $sendingTime = 0, $sent = FALSE) {
398
		$mail = $this->objectManager->get(Mail::class);
399
400
		$mail->setExtensionKey($extensionKey);
		$mail->setTemplateName($templateName);
401
402
		$mail->setFromAddress($this->fromAddress);
		$mail->setToAddress($this->toAddresses);
403
		$mail->setMailSubject($subject);
404
		$mail->setMailBody($emailBody);
405
		$mail->setPriority($priority);
406
407
		$mail->setBccAddresses(implode(',', $this->bccAddresses));
		$mail->setCcAddresses(implode(',', $this->ccAddresses));
408
		$mail->setSent($sent);
409
		$mail->setSendingTime($sendingTime);
410

411
		$mailRepository = $this->objectManager->get(MailRepository::class);
412
		$mailRepository->add($mail);
413
		$this->persistenceManager->persistAll();
414
	}
415

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
	/**
	 * Send a Mail from the queue, identified by its id
	 *
	 * @param int $uid
	 */
	public function sendMailFromQueue($uid) {
		$mailRepository = $this->objectManager->get(MailRepository::class);
		/** @var Mail $mailToSend */
		$mailToSend = $mailRepository->findByUid($uid)->getFirst();

		if ($mailToSend) {
			$this->mailMessage->setBody($mailToSend->getMailBody(), 'text/html');
			$this->mailMessage->setTo($mailToSend->getToAddress());
			$this->mailMessage->setFrom($mailToSend->getFromAddress(), $mailToSend->getFromName());
			$this->mailMessage->setSubject($mailToSend->getMailSubject());
431
432
433
			$this->mailMessage->setBcc(explode(',', $mailToSend->getBccAddresses()));
			$this->mailMessage->setCc(explode(',', $mailToSend->getCcAddresses()));
			$this->mailMessage->setReplyTo($mailToSend->getReplyTo());
434
435
436
437
			$this->mailMessage->send();
		}
	}

438
439
	/**
	 * @param array $registerArray
440
	 * @return void
441
	 */
442
	public static function setRegisterArray(array $registerArray) {
443
444
445
446
		self::$registerArray = $registerArray;
	}

	/**
447
	 * @param string $toAddresses
448
449
	 * @return MailTemplateService
	 */
450
451
452
	public function setToAddresses($toAddresses) {
		$this->toAddresses = $toAddresses;
		$this->mailMessage->setTo($toAddresses);
453
454
455
456
		return $this;
	}

	/**
457
	 * @param string $fromAddress
458
	 * @param string $fromName
459
460
	 * @return MailTemplateService
	 */
461
	public function setFromAddress($fromAddress, $fromName = '') {
462
		$this->fromAddress = $fromAddress;
463
		$this->mailMessage->setFrom($fromAddress, $fromName);
464
465
466
467
		return $this;
	}

	/**
468
	 * @param string $ccAddresses
469
470
	 * @return MailTemplateService
	 */
471
	public function setCcAddresses($ccAddresses) {
472
473
		$this->ccAddresses = $ccAddresses;
		$this->mailMessage->setCc(explode(',',$this->ccAddresses));
474
475
476
477
		return $this;
	}

	/**
478
	 * @param string $replyToAddress
479
480
	 * @return MailTemplateService
	 */
481
	public function setReplyToAddress($replyToAddress) {
482
		$this->replyToAddress = $replyToAddress;
483
		$this->mailMessage->setReplyTo($replyToAddress);
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
		return $this;
	}

	/**
	 * @param string $language
	 * @return MailTemplateService
	 */
	public function setLanguage($language) {
		$this->language = $language;
		return $this;
	}

	/**
	 * @param boolean $ignoreMailQueue
	 * @return MailTemplateService
	 */
	public function setIgnoreMailQueue($ignoreMailQueue) {
		$this->ignoreMailQueue = $ignoreMailQueue;
		return $this;
	}

	/**
	 * @param string $templateName
	 * @return MailTemplateService
	 */
	public function setTemplateName($templateName) {
		$this->templateName = $templateName;
		return $this;
	}

	/**
	 * @param string $extensionKey
	 * @return MailTemplateService
	 */
	public function setExtensionKey($extensionKey) {
		$this->extensionKey = $extensionKey;
		return $this;
	}

523
	/**
524
	 * @param array $markers
525
526
	 * @return MailTemplateService
	 */
527
528
	public function setMarkers(array $markers) {
		$this->markers = $markers;
529
530
		return $this;
	}
531
532

	/**
533
	 * @param string $bccAddresses
534
535
	 * @return MailTemplateService
	 */
536
537
538
	public function setBccAddresses($bccAddresses) {
		$this->bccAddresses = $bccAddresses;
		$this->mailMessage->setBcc(explode(',', $this->bccAddresses));
539
540
541
		return $this;
	}

542
543
544
545
546
547
548
549
	/**
	 * @param int $priority
	 * @return MailTemplateService
	 */
	public function setPriority($priority) {
		$this->priority = $priority;
		return $this;
	}
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564

	/**
	 * @param Swift_OutputByteStream $data
	 * @param string $path
	 * @param string $contentType
	 * @return MailTemplateService
	 */
	public function addAttachment($data, $filename, $contentType) {
		$attachment = Swift_Attachment::newInstance()
			->setFilename($filename)
			->setContentType($contentType)
			->setBody($data);
		$this->mailMessage->attach($attachment);
		return $this;
	}
565
566
567
568
569
570
571
572

	/**
	 * @return MailMessage
	 */
	public function getMailMessage() {
		return $this->mailMessage;
	}

573
574
575
576
577
578
579
580
581
582
583
	/**
	 * use all values from the given template
	 *
	 * @param Template $template
	 */
	private function loadTemplateValues($template) {
		$this->setFromAddress($template->getFromMail(), $template->getFromName());
		$this->setCcAddresses($template->getCc());
		$this->setBccAddresses($template->getBcc());
		$this->setReplyToAddress($template->getReplyTo());
	}
584
}