[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
v1
/
lib
/
pkp
/
classes
/
mail
/
[
Home
]
File: Mailer.php
<?php /** * @file classes/mail/Mailer.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class Mailer * * @ingroup mail * * @brief Represents interface to manage emails sending and view */ namespace PKP\mail; use APP\core\Application; use Exception; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Mail\Mailer as IlluminateMailer; use Illuminate\Mail\Message; use InvalidArgumentException; use PKP\config\Config; use PKP\observers\events\MessageSendingFromContext; use PKP\observers\events\MessageSendingFromSite; use PKP\site\Site; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Transport\TransportInterface; use Symfony\Component\Mime\Email; class Mailer extends IlluminateMailer { /** * Don't bind Laravel View Service, as it's not implemented * * @var null */ protected $views = null; /** * Maximum number of notification emails that can be sent per job */ public const BULK_EMAIL_SIZE_LIMIT = 50; /** * Creates new Mailer instance without binding with View * * @copydoc \Illuminate\Mail\Mailer::__construct() */ public function __construct(string $name, TransportInterface $transport, Dispatcher $events = null) { $this->name = $name; $this->transport = $transport; $this->events = $events; } /** * Renders email content into HTML string * * @param string|object $view * @param array $data variable => value, 'message' is reserved for the Laravel's Swift Message (Illuminate\Mail\Message) * * @throws Exception * * @see \Illuminate\Mail\Mailer::renderView() */ protected function renderView($view, $data): string { if ($view instanceof Htmlable) { // return HTML without data compiling return $view->toHtml(); } if (!is_string($view)) { throw new InvalidArgumentException('View must be instance of ' . Htmlable::class . ' or a string, ' . get_class($view) . ' is given'); } return $this->compileParams($view, $data); } /** * Compiles email templates by substituting variables with their real values * * @param string $view text or HTML string * @param array $data variables with their values passes ['variable' => value] * * @return string compiled string with substitute variables */ public function compileParams(string $view, array $data): string { $variables = []; $replacements = []; foreach ($data as $key => $value) { // Don't compile pre-set message data variables not belonging to the template if (in_array($key, Mailable::getReservedDataKeys())) { continue; } $variables[] = '/\{\$' . $key . '\}/'; $replacements[] = $value; } return preg_replace($variables, $replacements, $view); } /** * @copydoc IlluminateMailer::send() * * @param null|mixed $callback */ public function send($view, array $data = [], $callback = null) { if (is_a($view, Mailable::class)) { /** @var Mailable $view */ $view->setData(); } // Application is set to sandbox mode and will sent any emails to log if (Config::getVar('general', 'sandbox', false)) { error_log('Application is set to sandbox mode and will sent any emails to log'); } parent::send($view, $data, $callback); } /** * Overrides Illuminate Mailer method to provide additional parameters to the event * * @param \Symfony\Component\Mime\Email $message * @param array $data * * @return bool */ protected function shouldSendMessage($message, $data = []) { if (!$this->events) { return true; } if (array_key_exists(Mailable::DATA_KEY_CONTEXT, $data)) { $context = $data[Mailable::DATA_KEY_CONTEXT]; return $this->events->until(new MessageSendingFromContext($context, $message, $data)) !== false; } $site = Application::get()->getRequest()->getSite(); return $this->events->until(new MessageSendingFromSite($site, $message, $data)) !== false; } /** * Override method to catch an exception while sending email instance * * @return \Symfony\Component\Mailer\SentMessage|null */ protected function sendSymfonyMessage(Email $message) { $sentMessage = null; try { $sentMessage = $this->transport->send($message, Envelope::create($message)); } catch (TransportException $e) { error_log($e->getMessage()); } return $sentMessage; } /** * Overrides Illuminate Mailer method to modify email header * * @copydoc Illuminate\Mail\Mailer::addContent() */ protected function addContent($message, $view, $plain, $raw, $data): void { parent::addContent($message, $view, $plain, $raw, $data); $this->setEnvelopeSenderDefault($message, $data); $this->setDmarcCompliantFrom($message); } /** * Sets envelope sender, either the default one or from the context settings */ protected function setEnvelopeSenderDefault(Message $message, array $data): void { // Force default site-wide envelope sender if set $configDefaultEnvelopeSender = Config::getVar('email', 'default_envelope_sender'); if (Config::getVar('email', 'force_default_envelope_sender') && $configDefaultEnvelopeSender) { $message->sender($configDefaultEnvelopeSender); return; } // Don't provide further checks if envelope sender isn't allowed in the config if (!Config::getVar('email', 'allow_envelope_sender')) { return; } // Set the sender provided in the context settings $context = $data[Mailable::DATA_KEY_CONTEXT] ?? null; if ($context && $sender = $context->getData('envelopeSender')) { $message->sender($sender); return; } // Finally, provide default sender from the config if not specified if (!$message->getSender() && $configDefaultEnvelopeSender) { $message->sender($configDefaultEnvelopeSender); } } /** * Set DMARC compliant From header field body */ protected function setDmarcCompliantFrom(Message $message): void { if (empty($message->getFrom())) { return; } if (!( Config::getVar('email', 'force_default_envelope_sender') && Config::getVar('email', 'default_envelope_sender') && Config::getVar('email', 'force_dmarc_compliant_from') )) { return; } $this->promoteFromToReplyTo($message); } /** * If a DMARC compliant RFC5322.From was requested we need to promote the original RFC5322. From into a Reply-to header * and then munge the RFC5322.From */ protected function promoteFromToReplyTo(Message $message): void { $replyToEmails = array_map(fn ($x) => $x->getAddress(), $message->getReplyTo()); $fromEmails = array_map(fn ($x) => $x->getAddress(), $message->getFrom()); $alreadyExists = array_intersect($replyToEmails, $fromEmails); foreach ($message->getFrom() as $address) { if (!in_array($address->getAddress(), $alreadyExists)) { $message->addReplyTo($address); } } $site = Application::get()->getRequest()->getSite(); /** @var Site $site **/ $dmarcFromName = ''; if (Config::getVar('email', 'dmarc_compliant_from_displayname')) { $patterns = ['#%n#', '#%s#']; $replacements = [ implode(',', array_map(fn ($x) => $x->getName(), $message->getFrom())), $site->getLocalizedData('title'), ]; $dmarcFromName = preg_replace($patterns, $replacements, Config::getVar('email', 'dmarc_compliant_from_displayname')); } $message->from(Config::getVar('email', 'default_envelope_sender'), $dmarcFromName); } }