From e4b7a34f248b93e8664018fe5dd664e7d85218d0 Mon Sep 17 00:00:00 2001
From: Sveneld <sveneld300@gmail.com>
Date: Mon, 26 Feb 2024 21:39:02 +0100
Subject: [PATCH] Add MailSenderInterface Send mail via MailSenderInterface

---
 actions-web.php                    |  4 +-
 common.php                         | 39 +++++++++++-----
 src/Mail/DebugMailSender.php       | 11 +++++
 src/Mail/MailSenderInterface.php   |  8 ++++
 src/Mail/PHPMailerMailSender.php   | 58 +++++++++++++++++++++++
 tests/Mail/DebugMailSenderTest.php | 19 ++++++++
 tests/Mail/PHPMailerSenderTest.php | 74 ++++++++++++++++++++++++++++++
 7 files changed, 200 insertions(+), 13 deletions(-)
 create mode 100644 src/Mail/DebugMailSender.php
 create mode 100644 src/Mail/MailSenderInterface.php
 create mode 100644 src/Mail/PHPMailerMailSender.php
 create mode 100644 tests/Mail/DebugMailSenderTest.php
 create mode 100644 tests/Mail/PHPMailerSenderTest.php

diff --git a/actions-web.php b/actions-web.php
index 03bd975..1714955 100644
--- a/actions-web.php
+++ b/actions-web.php
@@ -740,7 +740,7 @@ function changecity($userid, $city)
 
 function resetpassword($number)
 {
-    global $db, $systemname, $systemrules, $systemURL;
+    global $db, $mailer, $systemrules, $systemURL;
 
     $number = $db->conn->real_escape_string(trim($number));
 
@@ -766,7 +766,7 @@ function resetpassword($number)
     _('Your password has been reset successfully.') . "\n\n" .
     _('Your new password is:') . "\n" . $password;
 
-    sendEmail($email, $subject, $message);
+    $mailer->send($email, $subject, $message);
     response(_('Your password has been reset successfully.') . ' ' . _('Check your email.'));
 }
 
diff --git a/common.php b/common.php
index 0c055c7..5e7aa23 100644
--- a/common.php
+++ b/common.php
@@ -1,5 +1,8 @@
 <?php
 
+use BikeShare\Mail\DebugMailSender;
+use BikeShare\Mail\MailSenderInterface;
+use BikeShare\Mail\PHPMailerMailSender;
 use BikeShare\SmsConnector\SmsConnectorFactory;
 
 require_once 'vendor/autoload.php';
@@ -16,6 +19,21 @@
     DEBUG
 );
 
+/**
+ * @var MailSenderInterface $mailer
+ */
+if (DEBUG===TRUE) {
+    $mailer = new DebugMailSender();
+} else {
+    $mailer = new PHPMailerMailSender(
+        $systemname,
+        $systememail,
+        $email,
+        new PHPMailer(false)
+    );
+}
+
+
 function error($message)
 {
    global $db;
@@ -275,19 +293,17 @@ function checkstandname($stand)
  **/
 function notifyAdmins($message, $notificationtype = 0)
 {
-    global $db, $systemname, $watches;
+    global $db, $systemname, $watches, $mailer;
 
     $result = $db->query('SELECT number,mail FROM users where privileges & 2 != 0');
     while ($row = $result->fetch_assoc()) {
         if ($notificationtype == 0) {
             sendSMS($row['number'], $message);
-            sendEmail($watches['email'], $systemname . ' ' . _('notification'), $message);
+            $mailer->send($watches['email'], $systemname . ' ' . _('notification'), $message);
         } else {
-            sendEmail($row['mail'], $systemname . ' ' . _('notification'), $message);
+            $mailer->send($row['mail'], $systemname . ' ' . _('notification'), $message);
         }
-    }
-
-//copy to Trello board -- might be added as a person instead
+    }//copy to Trello board -- might be added as a person instead
     if ($notificationtype == 0) {
         sendEmail('cyklokoalicia1+q31wfjphbgkuelf19hlb@boards.trello.com', $message, $message);
     }
@@ -295,7 +311,8 @@ function notifyAdmins($message, $notificationtype = 0)
 
 function sendConfirmationEmail($emailto)
 {
-    global $db, $dbpassword, $systemname, $systemrules, $systemURL;
+
+    global $db, $dbpassword, $systemname, $systemrules, $systemURL, $mailer;
 
     $subject = _('Registration');
 
@@ -312,10 +329,10 @@ function sendConfirmationEmail($emailto)
     $names = preg_split("/[\s,]+/", $row['userName']);
     $firstname = $names[0];
     $message = _('Hello') . ' ' . $firstname . ",\n\n" .
-    _('you have been registered into community bike share system') . ' ' . $systemname . ".\n\n" .
-    _('System rules are available here:') . "\n" . $systemrules . "\n\n" .
-    _('By clicking the following link you agree to the System rules:') . "\n" . $systemURL . 'agree.php?key=' . $userKey;
-    sendEmail($emailto, $subject, $message);
+        _('you have been registered into community bike share system') . ' ' . $systemname . ".\n\n" .
+        _('System rules are available here:') . "\n" . $systemrules . "\n\n" .
+        _('By clicking the following link you agree to the System rules:') . "\n" . $systemURL . 'agree.php?key=' . $userKey;
+    $mailer->send($emailto, $subject, $message);
 }
 
 function confirmUser($userKey)
diff --git a/src/Mail/DebugMailSender.php b/src/Mail/DebugMailSender.php
new file mode 100644
index 0000000..b4d59a8
--- /dev/null
+++ b/src/Mail/DebugMailSender.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace BikeShare\Mail;
+
+class DebugMailSender implements MailSenderInterface
+{
+    public function sendMail($recipient, $subject, $message)
+    {
+        echo $recipient, ' | ', $subject, ' | ', $message . PHP_EOL;
+    }
+}
\ No newline at end of file
diff --git a/src/Mail/MailSenderInterface.php b/src/Mail/MailSenderInterface.php
new file mode 100644
index 0000000..2cb9a57
--- /dev/null
+++ b/src/Mail/MailSenderInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace BikeShare\Mail;
+
+interface MailSenderInterface
+{
+    public function sendMail($recipient, $subject, $message);
+}
diff --git a/src/Mail/PHPMailerMailSender.php b/src/Mail/PHPMailerMailSender.php
new file mode 100644
index 0000000..a65af7b
--- /dev/null
+++ b/src/Mail/PHPMailerMailSender.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace BikeShare\Mail;
+
+class PHPMailerMailSender implements MailSenderInterface
+{
+    /**
+     * @var string
+     */
+    private $fromEmail;
+    /**
+     * @var string
+     */
+    private $fromName;
+    /**
+     * @var array
+     */
+    private $emailConfig;
+    /**
+     * @var \PHPMailer
+     */
+    private $mailer;
+
+    public function __construct(
+        $fromEmail = null,
+        $fromName = null,
+        array $emailConfig = null,
+        \PHPMailer $mailer = null
+    ) {
+
+        $this->fromEmail = $fromEmail;
+        $this->fromName = $fromName;
+        $this->emailConfig = $emailConfig;
+        $this->mailer = $mailer;
+    }
+
+    public function sendMail($recipient, $subject, $message)
+    {
+        $this->mailer->clearAllRecipients();
+
+        $this->mailer->isSMTP(); // Set mailer to use SMTP
+        //$this->mailer->SMTPDebug  = 2;
+        $this->mailer->Host = $this->emailConfig["smtp"]; // Specify main and backup SMTP servers
+        $this->mailer->Username = $this->emailConfig["user"]; // SMTP username
+        $this->mailer->Password = $this->emailConfig["pass"]; // SMTP password
+        $this->mailer->SMTPAuth = true; // Enable SMTP authentication
+        $this->mailer->SMTPSecure = "ssl"; // Enable SSL
+        $this->mailer->Port = 465; // TCP port to connect to
+        $this->mailer->CharSet = "UTF-8";
+        $this->mailer->From = $this->fromEmail;
+        $this->mailer->FromName = $this->fromName;
+        $this->mailer->addAddress($recipient);     // Add a recipient
+        $this->mailer->addBCC($this->fromEmail);     // Add a recipient
+        $this->mailer->Subject = $subject;
+        $this->mailer->Body = $message;
+        $this->mailer->send();
+    }
+}
diff --git a/tests/Mail/DebugMailSenderTest.php b/tests/Mail/DebugMailSenderTest.php
new file mode 100644
index 0000000..6bc8b5c
--- /dev/null
+++ b/tests/Mail/DebugMailSenderTest.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Test\BikeShare\Mail;
+
+use BikeShare\Mail\DebugMailSender;
+use PHPUnit\Framework\TestCase;
+
+class DebugMailSenderTest extends TestCase
+{
+    public function testSendMail()
+    {
+        $recipient = 'recipient';
+        $subject = 'subject';
+        $message = 'message';
+        $mailer = new DebugMailSender();
+        $mailer->sendMail($recipient, $subject, $message);
+        $this->expectOutputString($recipient . ' | ' . $subject . ' | ' . $message . PHP_EOL);
+    }
+}
diff --git a/tests/Mail/PHPMailerSenderTest.php b/tests/Mail/PHPMailerSenderTest.php
new file mode 100644
index 0000000..f4ad2bd
--- /dev/null
+++ b/tests/Mail/PHPMailerSenderTest.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Test\BikeShare\Mail;
+
+use BikeShare\Mail\PHPMailerMailSender;
+use PHPUnit\Framework\TestCase;
+
+class PHPMailerSenderTest extends TestCase
+{
+    /**
+     * @var \PHPMailer|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $mailer;
+    /**
+     * @var PHPMailerMailSender
+     */
+    private $mailSender;
+
+    protected function setUp()
+    {
+        $email = [
+            'smtp' => 'smtp',
+            'user' => 'user',
+            'pass' => 'pass',
+        ];
+
+        $this->mailer = $this->createMock(\PHPMailer::class);
+        $this->mailSender = new PHPMailerMailSender(
+            'fromEmail',
+            'fromName',
+            $email,
+            $this->mailer
+        );
+    }
+
+    public function testSendMail()
+    {
+        $recipient = 'recipient';
+        $subject = 'subject';
+        $message = 'message';
+
+        $this->mailer
+            ->expects($this->once())
+            ->method('clearAllRecipients');
+        $this->mailer
+            ->expects($this->once())
+            ->method('isSMTP');
+        $this->mailer
+            ->expects($this->once())
+            ->method('addAddress')
+            ->with($recipient);
+        $this->mailer
+            ->expects($this->once())
+            ->method('addBCC')
+            ->with('fromEmail');
+        $this->mailer
+            ->expects($this->once())
+            ->method('send');
+
+        $this->mailSender->sendMail($recipient, $subject, $message);
+
+        $this->assertEquals($this->mailer->Host, 'smtp');
+        $this->assertEquals($this->mailer->Username, 'user');
+        $this->assertEquals($this->mailer->Password, 'pass');
+        $this->assertEquals($this->mailer->SMTPAuth, true);
+        $this->assertEquals($this->mailer->SMTPSecure, 'ssl');
+        $this->assertEquals($this->mailer->Port, 465);
+        $this->assertEquals($this->mailer->CharSet, 'UTF-8');
+        $this->assertEquals($this->mailer->From, 'fromEmail');
+        $this->assertEquals($this->mailer->FromName, 'fromName');
+        $this->assertEquals($this->mailer->Subject, $subject);
+        $this->assertEquals($this->mailer->Body, $message);
+    }
+}