summaryrefslogtreecommitdiff
path: root/src/Mail
diff options
context:
space:
mode:
authorIgor Scheller <igor.scheller@igorshp.de>2018-09-05 13:40:03 +0200
committerIgor Scheller <igor.scheller@igorshp.de>2018-09-05 13:44:43 +0200
commit01e9c22695a3e495f07ab445750221af72e09fe4 (patch)
tree63c01a396d289f5f1e4d11259654e772300ff98c /src/Mail
parent9d34f371cb9c5ab0d60bd3158678b9cc9da6cc80 (diff)
Implemented mailing abstraction
Closes #434
Diffstat (limited to 'src/Mail')
-rw-r--r--src/Mail/EngelsystemMailer.php35
-rw-r--r--src/Mail/Mailer.php79
-rw-r--r--src/Mail/MailerServiceProvider.php86
-rw-r--r--src/Mail/Transport/LogTransport.php44
-rw-r--r--src/Mail/Transport/Transport.php103
5 files changed, 347 insertions, 0 deletions
diff --git a/src/Mail/EngelsystemMailer.php b/src/Mail/EngelsystemMailer.php
new file mode 100644
index 00000000..17047cc8
--- /dev/null
+++ b/src/Mail/EngelsystemMailer.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Engelsystem\Mail;
+
+use Engelsystem\Renderer\Renderer;
+use Swift_Mailer as SwiftMailer;
+
+class EngelsystemMailer extends Mailer
+{
+ /** @var Renderer|null */
+ protected $view;
+
+ public function __construct(SwiftMailer $mailer, Renderer $view = null)
+ {
+ parent::__construct($mailer);
+
+ $this->view = $view;
+ }
+
+ /**
+ * Send a template
+ *
+ * @param string $to
+ * @param string $subject
+ * @param string $template
+ * @param array $data
+ * @return int
+ */
+ public function sendView($to, $subject, $template, $data = []): int
+ {
+ $body = $this->view->render($template, $data);
+
+ return $this->send($to, $subject, $body);
+ }
+}
diff --git a/src/Mail/Mailer.php b/src/Mail/Mailer.php
new file mode 100644
index 00000000..ed800986
--- /dev/null
+++ b/src/Mail/Mailer.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Engelsystem\Mail;
+
+use Engelsystem\Renderer\Renderer;
+use Swift_Mailer as SwiftMailer;
+use Swift_Message as SwiftMessage;
+
+class Mailer
+{
+ /** @var SwiftMailer */
+ protected $mailer;
+
+ /** @var Renderer|null */
+ protected $view;
+
+ /** @var string */
+ protected $fromAddress = '';
+
+ /** @var string */
+ protected $fromName = null;
+
+ public function __construct(SwiftMailer $mailer)
+ {
+ $this->mailer = $mailer;
+ }
+
+ /**
+ * Send the mail
+ *
+ * @param string|string[] $to
+ * @param string $subject
+ * @param string $body
+ * @return int
+ */
+ public function send($to, string $subject, string $body): int
+ {
+ /** @var SwiftMessage $message */
+ $message = $this->mailer->createMessage();
+ $message->setTo((array)$to)
+ ->setFrom($this->fromAddress, $this->fromName)
+ ->setSubject($subject)
+ ->setBody($body);
+
+ return $this->mailer->send($message);
+ }
+
+ /**
+ * @return string
+ */
+ public function getFromAddress(): string
+ {
+ return $this->fromAddress;
+ }
+
+ /**
+ * @param string $fromAddress
+ */
+ public function setFromAddress(string $fromAddress)
+ {
+ $this->fromAddress = $fromAddress;
+ }
+
+ /**
+ * @return string
+ */
+ public function getFromName(): string
+ {
+ return $this->fromName;
+ }
+
+ /**
+ * @param string $fromName
+ */
+ public function setFromName(string $fromName)
+ {
+ $this->fromName = $fromName;
+ }
+}
diff --git a/src/Mail/MailerServiceProvider.php b/src/Mail/MailerServiceProvider.php
new file mode 100644
index 00000000..70cb0d30
--- /dev/null
+++ b/src/Mail/MailerServiceProvider.php
@@ -0,0 +1,86 @@
+<?php
+
+namespace Engelsystem\Mail;
+
+use Engelsystem\Config\Config;
+use Engelsystem\Container\ServiceProvider;
+use Engelsystem\Mail\Transport\LogTransport;
+use InvalidArgumentException;
+use Swift_Mailer as SwiftMailer;
+use Swift_SendmailTransport as SendmailTransport;
+use Swift_SmtpTransport as SmtpTransport;
+use Swift_Transport as Transport;
+
+class MailerServiceProvider extends ServiceProvider
+{
+ public function register()
+ {
+ /** @var Config $config */
+ $config = $this->app->get('config');
+ $mailConfig = $config->get('email');
+
+ $transport = $this->getTransport($mailConfig['driver'], $mailConfig);
+ $this->app->instance(Transport::class, $transport);
+ $this->app->instance('mailer.transport', $transport);
+
+ /** @var SwiftMailer $swiftMailer */
+ $swiftMailer = $this->app->make(SwiftMailer::class);
+ $this->app->instance(SwiftMailer::class, $swiftMailer);
+ $this->app->instance('mailer.swift', $swiftMailer);
+
+ /** @var Mailer $mailer */
+ $mailer = $this->app->make(EngelsystemMailer::class);
+ $mailer->setFromAddress($mailConfig['from']['address']);
+ if (!empty($mailConfig['from']['name'])) {
+ $mailer->setFromName($mailConfig['from']['name']);
+ }
+
+ $this->app->instance(EngelsystemMailer::class, $mailer);
+ $this->app->instance(Mailer::class, $mailer);
+ $this->app->instance('mailer', $mailer);
+ }
+
+ /**
+ * @param string $transport
+ * @param array $config
+ * @return Transport
+ */
+ protected function getTransport($transport, $config)
+ {
+ switch ($transport) {
+ case 'log':
+ return $this->app->make(LogTransport::class);
+ case 'mail':
+ case 'sendmail':
+ return $this->app->make(SendmailTransport::class, ['command' => $config['sendmail']]);
+ case 'smtp':
+ return $this->getSmtpTransport($config);
+ }
+
+ throw new InvalidArgumentException(sprintf('Mail driver "%s" not found', $transport));
+ }
+
+ /**
+ * @param array $config
+ * @return SmtpTransport
+ */
+ protected function getSmtpTransport(array $config)
+ {
+ /** @var SmtpTransport $transport */
+ $transport = $this->app->make(SmtpTransport::class, [
+ 'host' => $config['host'],
+ 'port' => $config['port'],
+ 'security' => $config['encryption'],
+ ]);
+
+ if ($config['username']) {
+ $transport->setUsername($config['username']);
+ }
+
+ if ($config['password']) {
+ $transport->setPassword($config['password']);
+ }
+
+ return $transport;
+ }
+}
diff --git a/src/Mail/Transport/LogTransport.php b/src/Mail/Transport/LogTransport.php
new file mode 100644
index 00000000..6e351302
--- /dev/null
+++ b/src/Mail/Transport/LogTransport.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Engelsystem\Mail\Transport;
+
+use Psr\Log\LoggerInterface;
+use Swift_Mime_SimpleMessage as SimpleMessage;
+
+class LogTransport extends Transport
+{
+ /** @var LoggerInterface */
+ protected $logger;
+
+ public function __construct(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
+
+ /**
+ * Send the given Message.
+ *
+ * Recipient/sender data will be retrieved from the Message API.
+ * The return value is the number of recipients
+ *
+ * @param SimpleMessage $message
+ * @param string[] $failedRecipients An array of failures by-reference
+ *
+ * @return int
+ */
+ public function send(
+ SimpleMessage $message,
+ &$failedRecipients = null
+ ): int {
+ $this->logger->debug(
+ 'Mail: Send mail "{title}" to "{recipients}":' . PHP_EOL . '{content}',
+ [
+ 'title' => $message->getSubject(),
+ 'recipients' => $this->getTo($message),
+ 'content' => (string)$message->getHeaders() . PHP_EOL . PHP_EOL . $message->toString(),
+ ]
+ );
+
+ return count($this->allRecipients($message));
+ }
+}
diff --git a/src/Mail/Transport/Transport.php b/src/Mail/Transport/Transport.php
new file mode 100644
index 00000000..691faf60
--- /dev/null
+++ b/src/Mail/Transport/Transport.php
@@ -0,0 +1,103 @@
+<?php
+
+namespace Engelsystem\Mail\Transport;
+
+use Swift_Events_EventListener;
+use Swift_Mime_SimpleMessage as SimpleMessage;
+use Swift_Transport as SwiftTransport;
+
+abstract class Transport implements SwiftTransport
+{
+ /**
+ * Test if this Transport mechanism has started.
+ *
+ * @return bool
+ */
+ public function isStarted(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Start this Transport mechanism.
+ */
+ public function start() { }
+
+ /**
+ * Stop this Transport mechanism.
+ */
+ public function stop() { }
+
+ /**
+ * Check if this Transport mechanism is alive.
+ *
+ * If a Transport mechanism session is no longer functional, the method
+ * returns FALSE. It is the responsibility of the developer to handle this
+ * case and restart the Transport mechanism manually.
+ *
+ * @example
+ *
+ * if (!$transport->ping()) {
+ * $transport->stop();
+ * $transport->start();
+ * }
+ *
+ * The Transport mechanism will be started, if it is not already.
+ *
+ * It is undefined if the Transport mechanism attempts to restart as long as
+ * the return value reflects whether the mechanism is now functional.
+ *
+ * @return bool TRUE if the transport is alive
+ */
+ public function ping(): bool
+ {
+ return true;
+ }
+
+ /**
+ * Register a plugin in the Transport.
+ *
+ * @param Swift_Events_EventListener $plugin
+ */
+ public function registerPlugin(Swift_Events_EventListener $plugin) { }
+
+ /**
+ * Returns a unified list of all recipients
+ *
+ * @param SimpleMessage $message
+ * @return array
+ */
+ protected function allRecipients(SimpleMessage $message): array
+ {
+ return array_merge(
+ (array)$message->getTo(),
+ (array)$message->getCc(),
+ (array)$message->getBcc()
+ );
+ }
+
+ /**
+ * Returns a concatenated list of mail recipients
+ *
+ * @param SimpleMessage $message
+ * @return string
+ */
+ protected function getTo(SimpleMessage $message): string
+ {
+ return $this->formatTo($this->allRecipients($message));
+ }
+
+ /**
+ * @param array $recipients
+ * @return string
+ */
+ protected function formatTo(array $recipients)
+ {
+ $list = [];
+ foreach ($recipients as $address => $name) {
+ $list[] = $name ? sprintf('%s <%s>', $name, $address) : $address;
+ }
+
+ return implode(',', $list);
+ }
+}