1<?php declare(strict_types=1); 2 3/* 4 * This file is part of the Monolog package. 5 * 6 * (c) Jordi Boggiano <j.boggiano@seld.be> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Monolog\Handler; 13 14use Monolog\Logger; 15use Monolog\Utils; 16use Monolog\Formatter\FormatterInterface; 17use Monolog\Formatter\LineFormatter; 18use Swift_Message; 19use Swift; 20 21/** 22 * SwiftMailerHandler uses Swift_Mailer to send the emails 23 * 24 * @author Gyula Sallai 25 * 26 * @phpstan-import-type Record from \Monolog\Logger 27 */ 28class SwiftMailerHandler extends MailHandler 29{ 30 /** @var \Swift_Mailer */ 31 protected $mailer; 32 /** @var Swift_Message|callable(string, Record[]): Swift_Message */ 33 private $messageTemplate; 34 35 /** 36 * @psalm-param Swift_Message|callable(string, Record[]): Swift_Message $message 37 * 38 * @param \Swift_Mailer $mailer The mailer to use 39 * @param callable|Swift_Message $message An example message for real messages, only the body will be replaced 40 */ 41 public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true) 42 { 43 parent::__construct($level, $bubble); 44 45 $this->mailer = $mailer; 46 $this->messageTemplate = $message; 47 } 48 49 /** 50 * {@inheritDoc} 51 */ 52 protected function send(string $content, array $records): void 53 { 54 $this->mailer->send($this->buildMessage($content, $records)); 55 } 56 57 /** 58 * Gets the formatter for the Swift_Message subject. 59 * 60 * @param string|null $format The format of the subject 61 */ 62 protected function getSubjectFormatter(?string $format): FormatterInterface 63 { 64 return new LineFormatter($format); 65 } 66 67 /** 68 * Creates instance of Swift_Message to be sent 69 * 70 * @param string $content formatted email body to be sent 71 * @param array $records Log records that formed the content 72 * @return Swift_Message 73 * 74 * @phpstan-param Record[] $records 75 */ 76 protected function buildMessage(string $content, array $records): Swift_Message 77 { 78 $message = null; 79 if ($this->messageTemplate instanceof Swift_Message) { 80 $message = clone $this->messageTemplate; 81 $message->generateId(); 82 } elseif (is_callable($this->messageTemplate)) { 83 $message = ($this->messageTemplate)($content, $records); 84 } 85 86 if (!$message instanceof Swift_Message) { 87 $record = reset($records); 88 throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : '')); 89 } 90 91 if ($records) { 92 $subjectFormatter = $this->getSubjectFormatter($message->getSubject()); 93 $message->setSubject($subjectFormatter->format($this->getHighestRecord($records))); 94 } 95 96 $mime = 'text/plain'; 97 if ($this->isHtmlBody($content)) { 98 $mime = 'text/html'; 99 } 100 101 $message->setBody($content, $mime); 102 /** @phpstan-ignore-next-line */ 103 if (version_compare(Swift::VERSION, '6.0.0', '>=')) { 104 $message->setDate(new \DateTimeImmutable()); 105 } else { 106 /** @phpstan-ignore-next-line */ 107 $message->setDate(time()); 108 } 109 110 return $message; 111 } 112} 113