MailTemplateService.php 15.8 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
65
66
67
68
69
70
71
72
	/**
	 * @var string
	 */
	const MARKER_TYPE_ARRAY = 'Array';

	/**
	 * @var string
	 */
	const MARKER_TYPE_OBJECT = 'Object';

73
	/**
74
	 * @var array $registerArray
75
	 */
76
	private static $registerArray = [];
77

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

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

	/**
89
	 * @var array $ccAddresses
90
	 */
91
	private $ccAddresses = [];
92
93

	/**
94
	 * @var string $replyToAddress
95
	 */
96
	private $replyToAddress;
97
98

	/**
99
	 * @var string $language
100
	 */
101
	private $language;
102
103

	/**
104
	 * @var boolean $ignoreMailQueue
105
	 */
106
	private $ignoreMailQueue = FALSE;
107
108
109
110
111
112
113

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

	/**
114
	 * @var string $templateName
115
116
117
118
	 */
	private $templateName;

	/**
119
	 * @var string $extensionKey
120
121
122
123
	 */
	private $extensionKey;

	/**
124
	 * @var array $markers
125
	 */
126
	private $markers = [];
127

128
129
130
	/**
	 * holds the TypoScript configuration for sg_mail
	 *
131
	 * @var array $tsSettings
132
133
134
	 */
	private $tsSettings = [];

135
136
137
138
139
	/**
	 * @var array $bccAddresses
	 */
	private $bccAddresses = [];

140
141
142
143
144
	/**
	 * @var int
	 */
	private $priority = Mail::PRIORITY_LOWEST;

145
146
147
	/**
	 * @var \SGalinski\SgMail\Domain\Repository\TemplateRepository
	 */
148
149
150
151
152
153
	protected $templateRepository;

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

155
156
157
158
159
	/**
	 * @var \TYPO3\CMS\Extbase\Object\ObjectManager
	 */
	protected $objectManager;

160
161
162
163
164
	/**
	 * @var array
	 */
	private $attachments = [];

165
166
167
168
	/**
	 * MailTemplateService constructor.
	 */
	public function __construct() {
169
170
171
172
173
174
		/** @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);
175
176
		$this->tsSettings = $typoScriptSettingsService->getSettings(0, 'tx_sgmail');
		$this->language = $this->tsSettings['templateDefaultLanguage'];
177
178
179
180
		/** @var TemplateRepository templateRepository */
		$this->templateRepository = $this->objectManager->get(TemplateRepository::class);
		/** @var PersistenceManager persistenceManager */
		$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);
181
182
183

		$this->fromAddress = $this->tsSettings['mail']['default']['from'];
		$this->mailMessage->setFrom($this->fromAddress);
184
		$this->bccAddresses = GeneralUtility::trimExplode(',', $this->tsSettings['mail']['default']['bcc']);
185
186
187
188
189
190
191
192
193
194
195
196
197
198
		$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]);
			}
		}

199
		$this->mailMessage->setFrom($this->fromAddress);
200
		if (count($this->bccAddresses) > 0) {
201
202
203
			$this->mailMessage->setBcc($this->bccAddresses);
		}

204
		if (count($this->ccAddresses) > 0) {
205
206
			$this->mailMessage->setCc($this->ccAddresses);
		}
207
208
	}

Torsten Oppermann's avatar
Torsten Oppermann committed
209
	/**
Torsten Oppermann's avatar
Torsten Oppermann committed
210
	 * register a template with sg_mail
Fabian Galinski's avatar
Fabian Galinski committed
211
	 *
212
213
214
	 * 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
	 *
215
	 * @param string $extension
Torsten Oppermann's avatar
Torsten Oppermann committed
216
217
	 * @param string $templateName
	 * @param string $templatePath
218
	 * @param mixed $description
219
	 * @param array $markers
220
	 * @param mixed $subject
Torsten Oppermann's avatar
Torsten Oppermann committed
221
	 */
222
	public static function registerTemplate(
223
		$extension, $templateName, $templatePath, $description, array $markers, $subject
224
	) {
225
		MailTemplateService::$registerArray[$extension][$templateName] = [
226
			'templatePath' => $templatePath,
227
			'description' => $description,
228
			'marker' => $markers,
229
			'extension' => $extension,
230
			'templateName' => $templateName,
231
			'subject' => $subject
232
233
		];
	}
234

235
236
237
238
239
240
241
242
243
	/**
	 * 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') {
244
		$languagePath = 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang.xlf:' . $translationKey;
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

		// 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;
	}

265
	/**
Torsten Oppermann's avatar
Torsten Oppermann committed
266
	 * Get all registered templates
Fabian Galinski's avatar
Fabian Galinski committed
267
	 *
268
	 * @return array
269
	 */
270
271
	public static function getRegisterArray() {
		return self::$registerArray;
272
	}
273

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	/**
	 * 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());
294
			return TRUE;
295
296
		}

297
		return FALSE;
298
299
	}

300
	/**
301
	 * Send the Email
302
	 *
Torsten Oppermann's avatar
Torsten Oppermann committed
303
	 * @param boolean $isPreview
304
	 * @return boolean email was sent or added to mail queue successfully?
305
	 */
306
	public function sendEmail($isPreview = FALSE) {
307
		/** @var Template $template */
308
		$template = $this->templateRepository->findOneByTemplate(
309
			$this->extensionKey, $this->templateName, $this->language
310
		);
311

312
313
314
315
316
		// if there is a template, prefer those values
		if ($template) {
			$this->loadTemplateValues($template);
		}

317
318
319
320
321
322
323
324
		// 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
325
				$this->setLanguage('en');
326
327
328
329
330
331
332
				// does an english default template exist ?
				if (file_exists($templatePath . $this->language . '.template.html')) {
					$this->sendEmail();
					return TRUE;
				}

				return FALSE;
333
			}
334
335
		}

Torsten Oppermann's avatar
Torsten Oppermann committed
336
337
338
339
		if ($isPreview) {
			$previewMarker = [];
			$markerArray = self::$registerArray[$this->extensionKey][$this->templateName]['marker'];
			foreach ($markerArray as $marker) {
340
341
342
343
344
345
346
				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
347
			}
348
			$this->setIgnoreMailQueue(TRUE);
Torsten Oppermann's avatar
Torsten Oppermann committed
349
350
351
			$this->setMarkers($previewMarker);
		}

352
		/** @var StandaloneView $emailView */
353
		$emailView = $this->objectManager->get(StandaloneView::class);
354

355
356
		if (!isset($defaultTemplateContent)) {
			$emailView->setTemplateSource($template->getContent());
357
			$subject = $template->getSubject();
358
359
		} else {
			$emailView->setTemplateSource($defaultTemplateContent);
360
361
362
363
364
365
366
367
368
369

			$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
				);
			}
370
		}
371
		$this->mailMessage->setSubject($subject);
372

373
		$emailView->assignMultiple($this->markers);
374
		$emailBody = $emailView->render();
375

376
377
378
379
		// 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) {
380

381
			$this->mailMessage->setBody($emailBody, 'text/html');
382
			$this->mailMessage->send();
383
384
385
386
387
388
			$dateTime = new DateTime();
			$this->addMailToMailQueue(
				$this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority, $dateTime->getTimestamp(), TRUE
			);


389
		} else {
390
			$this->addMailToMailQueue($this->extensionKey, $this->templateName, $subject, $emailBody, $this->priority);
391
		}
392
393

		return TRUE;
394
395
396
	}

	/**
397
	 * Adds a new mail to the mail queue.
398
	 *
399
400
	 * @param string $extensionKey
	 * @param string $templateName
401
	 * @param string $subject
402
	 * @param string $emailBody
403
	 * @param int $sendingTime
404
	 * @param int $priority
405
	 * @param bool $sent
406
	 */
407
	private function addMailToMailQueue($extensionKey, $templateName, $subject, $emailBody, $priority, $sendingTime = 0, $sent = FALSE) {
408
		$mail = $this->objectManager->get(Mail::class);
409
410
		$mail->setExtensionKey($extensionKey);
		$mail->setTemplateName($templateName);
411
412
		$mail->setFromAddress($this->fromAddress);
		$mail->setToAddress($this->toAddresses);
413
		$mail->setMailSubject($subject);
414
		$mail->setMailBody($emailBody);
415
		$mail->setPriority($priority);
416
417
		$mail->setBccAddresses(implode(',', $this->bccAddresses));
		$mail->setCcAddresses(implode(',', $this->ccAddresses));
418
		$mail->setSent($sent);
419
		$mail->setSendingTime($sendingTime);
420

421
		$mailRepository = $this->objectManager->get(MailRepository::class);
422
		$mailRepository->add($mail);
423
		$this->persistenceManager->persistAll();
424
	}
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
	/**
	 * 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());
441
442
443
			$this->mailMessage->setBcc(explode(',', $mailToSend->getBccAddresses()));
			$this->mailMessage->setCc(explode(',', $mailToSend->getCcAddresses()));
			$this->mailMessage->setReplyTo($mailToSend->getReplyTo());
444
445
446
447
			$this->mailMessage->send();
		}
	}

448
449
	/**
	 * @param array $registerArray
450
	 * @return void
451
	 */
452
	public static function setRegisterArray(array $registerArray) {
453
454
455
456
		self::$registerArray = $registerArray;
	}

	/**
457
	 * @param string $toAddresses
458
459
	 * @return MailTemplateService
	 */
460
461
462
	public function setToAddresses($toAddresses) {
		$this->toAddresses = $toAddresses;
		$this->mailMessage->setTo($toAddresses);
463
464
465
466
		return $this;
	}

	/**
467
	 * @param string $fromAddress
468
	 * @param string $fromName
469
470
	 * @return MailTemplateService
	 */
471
	public function setFromAddress($fromAddress, $fromName = '') {
472
		$this->fromAddress = $fromAddress;
473
		$this->mailMessage->setFrom($fromAddress, $fromName);
474
475
476
477
		return $this;
	}

	/**
478
	 * @param string $ccAddresses
479
480
	 * @return MailTemplateService
	 */
481
	public function setCcAddresses($ccAddresses) {
482
483
		$this->ccAddresses = $ccAddresses;
		$this->mailMessage->setCc(explode(',',$this->ccAddresses));
484
485
486
487
		return $this;
	}

	/**
488
	 * @param string $replyToAddress
489
490
	 * @return MailTemplateService
	 */
491
	public function setReplyToAddress($replyToAddress) {
492
		$this->replyToAddress = $replyToAddress;
493
		$this->mailMessage->setReplyTo($replyToAddress);
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
523
524
525
526
527
528
529
530
531
532
		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;
	}

533
	/**
534
	 * @param array $markers
535
536
	 * @return MailTemplateService
	 */
537
538
	public function setMarkers(array $markers) {
		$this->markers = $markers;
539
540
		return $this;
	}
541
542

	/**
543
	 * @param string $bccAddresses
544
545
	 * @return MailTemplateService
	 */
546
547
548
	public function setBccAddresses($bccAddresses) {
		$this->bccAddresses = $bccAddresses;
		$this->mailMessage->setBcc(explode(',', $this->bccAddresses));
549
550
551
		return $this;
	}

552
553
554
555
556
557
558
559
	/**
	 * @param int $priority
	 * @return MailTemplateService
	 */
	public function setPriority($priority) {
		$this->priority = $priority;
		return $this;
	}
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574

	/**
	 * @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;
	}
575
576
577
578
579
580
581
582

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

583
584
585
586
587
588
589
590
591
592
593
	/**
	 * 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());
	}
594
}