Skip to content

Commit 83dc7fa

Browse files
laoneoheelc29
andauthored
Introduce a mailer interface and the respective factory (#40560)
* Add mailer interface and the respective factory * cs * cs * protected * cs * Update libraries/src/Mail/MailerInterface.php Co-authored-by: heelc29 <[email protected]> * Update libraries/src/Mail/MailerFactory.php Co-authored-by: heelc29 <[email protected]> * Update libraries/src/Mail/MailerFactory.php Co-authored-by: heelc29 <[email protected]> * Update libraries/src/Mail/MailerFactoryAwareTrait.php Co-authored-by: heelc29 <[email protected]> * Update libraries/src/Mail/MailerFactory.php Co-authored-by: heelc29 <[email protected]> * signature * inherit default settings * docs * cs * Update libraries/src/Mail/MailerFactoryAwareInterface.php Co-authored-by: heelc29 <[email protected]> * Update libraries/src/Mail/MailerFactory.php Co-authored-by: heelc29 <[email protected]> * Update libraries/src/Mail/MailerFactoryInterface.php Co-authored-by: heelc29 <[email protected]> * Default to null --------- Co-authored-by: heelc29 <[email protected]>
1 parent e6d204c commit 83dc7fa

File tree

13 files changed

+753
-70
lines changed

13 files changed

+753
-70
lines changed

administrator/components/com_config/src/Model/ApplicationModel.php

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
use Joomla\CMS\Language\Text;
2424
use Joomla\CMS\Log\Log;
2525
use Joomla\CMS\Mail\Exception\MailDisabledException;
26+
use Joomla\CMS\Mail\MailerFactoryAwareInterface;
27+
use Joomla\CMS\Mail\MailerFactoryAwareTrait;
2628
use Joomla\CMS\Mail\MailTemplate;
2729
use Joomla\CMS\MVC\Model\FormModel;
2830
use Joomla\CMS\Table\Asset;
@@ -45,8 +47,10 @@
4547
*
4648
* @since 3.2
4749
*/
48-
class ApplicationModel extends FormModel
50+
class ApplicationModel extends FormModel implements MailerFactoryAwareInterface
4951
{
52+
use MailerFactoryAwareTrait;
53+
5054
/**
5155
* Array of protected password fields from the configuration.php
5256
*
@@ -1178,22 +1182,23 @@ public function sendTestMail()
11781182
$input = $app->getInput()->json;
11791183
$smtppass = $input->get('smtppass', null, 'RAW');
11801184

1181-
$app->set('smtpauth', $input->get('smtpauth'));
1182-
$app->set('smtpuser', $input->get('smtpuser', '', 'STRING'));
1183-
$app->set('smtphost', $input->get('smtphost'));
1184-
$app->set('smtpsecure', $input->get('smtpsecure'));
1185-
$app->set('smtpport', $input->get('smtpport'));
1186-
$app->set('mailfrom', $input->get('mailfrom', '', 'STRING'));
1187-
$app->set('fromname', $input->get('fromname', '', 'STRING'));
1188-
$app->set('mailer', $input->get('mailer'));
1189-
$app->set('mailonline', $input->get('mailonline'));
1185+
$config = new Registry();
1186+
$config->set('smtpauth', $input->get('smtpauth'));
1187+
$config->set('smtpuser', $input->get('smtpuser', '', 'STRING'));
1188+
$config->set('smtphost', $input->get('smtphost'));
1189+
$config->set('smtpsecure', $input->get('smtpsecure'));
1190+
$config->set('smtpport', $input->get('smtpport'));
1191+
$config->set('mailfrom', $input->get('mailfrom', '', 'STRING'));
1192+
$config->set('fromname', $input->get('fromname', '', 'STRING'));
1193+
$config->set('mailer', $input->get('mailer'));
1194+
$config->set('mailonline', $input->get('mailonline'));
11901195

11911196
// Use smtppass only if it was submitted
11921197
if ($smtppass !== null) {
1193-
$app->set('smtppass', $smtppass);
1198+
$config->set('smtppass', $smtppass);
11941199
}
11951200

1196-
$mail = Factory::getMailer();
1201+
$mail = $this->getMailerFactory()->createMailer($config);
11971202

11981203
// Prepare email and try to send it
11991204
$mailer = new MailTemplate('com_config.test_mail', $user->getParam('language', $app->get('language')), $mail);

libraries/src/Extension/Service/Provider/MVCFactory.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use Joomla\CMS\Cache\CacheControllerFactoryInterface;
1313
use Joomla\CMS\Form\FormFactoryInterface;
14+
use Joomla\CMS\Mail\MailerFactoryInterface;
1415
use Joomla\CMS\MVC\Factory\ApiMVCFactory;
1516
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
1617
use Joomla\CMS\Router\SiteRouter;
@@ -78,6 +79,7 @@ function (Container $container) {
7879
$factory->setSiteRouter($container->get(SiteRouter::class));
7980
$factory->setCacheControllerFactory($container->get(CacheControllerFactoryInterface::class));
8081
$factory->setUserFactory($container->get(UserFactoryInterface::class));
82+
$factory->setMailerFactory($container->get(MailerFactoryInterface::class));
8183

8284
return $factory;
8385
}

libraries/src/Factory.php

Lines changed: 16 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,14 @@
1919
use Joomla\CMS\Filesystem\Stream;
2020
use Joomla\CMS\Language\Language;
2121
use Joomla\CMS\Language\LanguageFactoryInterface;
22-
use Joomla\CMS\Log\Log;
2322
use Joomla\CMS\Mail\Mail;
24-
use Joomla\CMS\Mail\MailHelper;
23+
use Joomla\CMS\Mail\MailerFactoryInterface;
2524
use Joomla\CMS\Session\Session;
2625
use Joomla\CMS\User\User;
2726
use Joomla\Database\DatabaseDriver;
2827
use Joomla\Database\DatabaseInterface;
2928
use Joomla\DI\Container;
3029
use Joomla\Registry\Registry;
31-
use PHPMailer\PHPMailer\Exception as phpmailerException;
3230

3331
// phpcs:disable PSR1.Files.SideEffects
3432
\defined('JPATH_PLATFORM') or die;
@@ -480,6 +478,11 @@ public static function getDbo()
480478
*
481479
* @see Mail
482480
* @since 1.7.0
481+
*
482+
* @deprecated __DEPLOY_VERSION__ will be removed in 6.0
483+
* Use the mailer service in the DI container and create a mailer from there
484+
* Example:
485+
* Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer();
483486
*/
484487
public static function getMailer()
485488
{
@@ -611,6 +614,7 @@ protected static function createContainer(): Container
611614
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Form())
612615
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Logger())
613616
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Language())
617+
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Mailer())
614618
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Menu())
615619
->registerServiceProvider(new \Joomla\CMS\Service\Provider\Pathway())
616620
->registerServiceProvider(new \Joomla\CMS\Service\Provider\HTMLRegistry())
@@ -693,56 +697,20 @@ protected static function createDbo()
693697
*
694698
* @see Mail
695699
* @since 1.7.0
700+
*
701+
* @deprecated __DEPLOY_VERSION__ will be removed in 6.0
702+
* Use the mailer service in the DI container and create a mailer from there
703+
* Example:
704+
* Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer();
696705
*/
697706
protected static function createMailer()
698707
{
699-
$conf = self::getConfig();
700-
701-
$smtpauth = ($conf->get('smtpauth') == 0) ? null : 1;
702-
$smtpuser = $conf->get('smtpuser');
703-
$smtppass = $conf->get('smtppass');
704-
$smtphost = $conf->get('smtphost');
705-
$smtpsecure = $conf->get('smtpsecure');
706-
$smtpport = $conf->get('smtpport');
707-
$mailfrom = $conf->get('mailfrom');
708-
$fromname = $conf->get('fromname');
709-
$mailer = $conf->get('mailer');
710-
711-
// Create a Mail object
712-
$mail = Mail::getInstance();
713-
714-
// Clean the email address
715-
$mailfrom = MailHelper::cleanLine($mailfrom);
716-
717-
// Set default sender without Reply-to if the mailfrom is a valid address
718-
if (MailHelper::isEmailAddress($mailfrom)) {
719-
// Wrap in try/catch to catch phpmailerExceptions if it is throwing them
720-
try {
721-
// Check for a false return value if exception throwing is disabled
722-
if ($mail->setFrom($mailfrom, MailHelper::cleanLine($fromname), false) === false) {
723-
Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail');
724-
}
725-
} catch (phpmailerException $e) {
726-
Log::add(__METHOD__ . '() could not set the sender data.', Log::WARNING, 'mail');
727-
}
728-
}
708+
$mailer = self::getContainer()->get(MailerFactoryInterface::class)->createMailer(self::getConfig());
729709

730-
// Default mailer is to use PHP's mail function
731-
switch ($mailer) {
732-
case 'smtp':
733-
$mail->useSmtp($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport);
734-
break;
735-
736-
case 'sendmail':
737-
$mail->isSendmail();
738-
break;
739-
740-
default:
741-
$mail->isMail();
742-
break;
743-
}
710+
// This needs to be set here for backwards compatibility
711+
Mail::$instances['Joomla'] = $mailer;
744712

745-
return $mail;
713+
return $mailer;
746714
}
747715

748716
/**

libraries/src/MVC/Factory/MVCFactory.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Joomla\CMS\Factory;
1616
use Joomla\CMS\Form\FormFactoryAwareInterface;
1717
use Joomla\CMS\Form\FormFactoryAwareTrait;
18+
use Joomla\CMS\Mail\MailerFactoryAwareInterface;
19+
use Joomla\CMS\Mail\MailerFactoryAwareTrait;
1820
use Joomla\CMS\MVC\Model\ModelInterface;
1921
use Joomla\CMS\Router\SiteRouterAwareInterface;
2022
use Joomla\CMS\Router\SiteRouterAwareTrait;
@@ -37,14 +39,15 @@
3739
*
3840
* @since 3.10.0
3941
*/
40-
class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface, SiteRouterAwareInterface, UserFactoryAwareInterface
42+
class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface, SiteRouterAwareInterface, UserFactoryAwareInterface, MailerFactoryAwareInterface
4143
{
4244
use FormFactoryAwareTrait;
4345
use DispatcherAwareTrait;
4446
use DatabaseAwareTrait;
4547
use SiteRouterAwareTrait;
4648
use CacheControllerFactoryAwareTrait;
4749
use UserFactoryAwareTrait;
50+
use MailerFactoryAwareTrait;
4851

4952
/**
5053
* The namespace to create the objects from.
@@ -99,6 +102,7 @@ public function createController($name, $prefix, array $config, CMSApplicationIn
99102
$this->setRouterOnObject($controller);
100103
$this->setCacheControllerOnObject($controller);
101104
$this->setUserFactoryOnObject($controller);
105+
$this->setMailerFactoryOnObject($controller);
102106

103107
return $controller;
104108
}
@@ -145,6 +149,7 @@ public function createModel($name, $prefix = '', array $config = [])
145149
$this->setRouterOnObject($model);
146150
$this->setCacheControllerOnObject($model);
147151
$this->setUserFactoryOnObject($model);
152+
$this->setMailerFactoryOnObject($model);
148153

149154
if ($model instanceof DatabaseAwareInterface) {
150155
try {
@@ -391,4 +396,26 @@ private function setUserFactoryOnObject($object): void
391396
// Ignore it
392397
}
393398
}
399+
400+
/**
401+
* Sets the internal mailer factory on the given object.
402+
*
403+
* @param object $object The object
404+
*
405+
* @return void
406+
*
407+
* @since __DEPLOY_VERSION__
408+
*/
409+
private function setMailerFactoryOnObject($object): void
410+
{
411+
if (!$object instanceof MailerFactoryAwareInterface) {
412+
return;
413+
}
414+
415+
try {
416+
$object->setMailerFactory($this->getMailerFactory());
417+
} catch (\UnexpectedValueException $e) {
418+
// Ignore it
419+
}
420+
}
394421
}

libraries/src/Mail/Mail.php

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,18 @@
2525
*
2626
* @since 1.7.0
2727
*/
28-
class Mail extends PHPMailer
28+
class Mail extends PHPMailer implements MailerInterface
2929
{
3030
/**
3131
* Mail instances container.
3232
*
3333
* @var Mail[]
3434
* @since 1.7.3
35+
*
36+
* @deprecated __DEPLOY_VERSION__ will be removed in 6.0
37+
* See getInstance() for more details
3538
*/
36-
protected static $instances = [];
39+
public static $instances = [];
3740

3841
/**
3942
* Charset of the message.
@@ -100,12 +103,19 @@ public function __construct($exceptions = true)
100103
*
101104
* @return Mail The global Mail object
102105
*
103-
* @since 1.7.0
106+
* @since __DEPLOY_VERSION__
107+
*
108+
* @deprecated __DEPLOY_VERSION__ will be removed in 6.0
109+
* Use the mailer service in the DI container and create a mailer from there
110+
* Example:
111+
* Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer();
104112
*/
105113
public static function getInstance($id = 'Joomla', $exceptions = true)
106114
{
107115
if (empty(static::$instances[$id])) {
108-
static::$instances[$id] = new static($exceptions);
116+
$config = clone Factory::getConfig();
117+
$config->set('throw_exceptions', $exceptions);
118+
static::$instances[$id] = Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer($config);
109119
}
110120

111121
return static::$instances[$id];
@@ -172,9 +182,10 @@ public function Send()
172182
/**
173183
* Set the email sender
174184
*
175-
* @param mixed $from email address and Name of sender
176-
* <code>array([0] => email Address, [1] => Name)</code>
177-
* or as a string
185+
* @param mixed $from email address and Name of sender
186+
* <code>array([0] => email Address, [1] => Name)</code>
187+
* or as a string
188+
* @param mixed $name Either a string or array of strings [name(s)]
178189
*
179190
* @return Mail|boolean Returns this object for chaining on success or boolean false on failure.
180191
*
@@ -183,7 +194,7 @@ public function Send()
183194
* @throws \UnexpectedValueException if the sender is not a valid address
184195
* @throws phpmailerException if setting the sender failed and exception throwing is enabled
185196
*/
186-
public function setSender($from)
197+
public function setSender($from, $name = '')
187198
{
188199
if (\is_array($from)) {
189200
// If $from is an array we assume it has an address and a name
@@ -195,7 +206,7 @@ public function setSender($from)
195206
}
196207
} elseif (\is_string($from)) {
197208
// If it is a string we assume it is just the address
198-
$result = $this->setFrom(MailHelper::cleanLine($from));
209+
$result = $this->setFrom(MailHelper::cleanLine($from), $name);
199210
} else {
200211
// If it is neither, we log a message and throw an exception
201212
Log::add(Text::sprintf('JLIB_MAIL_INVALID_EMAIL_SENDER', $from), Log::WARNING, 'jerror');

0 commit comments

Comments
 (0)