0

The issue

Quoting (again) from an old question of mine:

I have a form in my Joomla! site. Once completed, the form should send an e-mail but only if some conditions have been met.

Not having been able to use standard, commercially available mailers while also checking those conditions, I am using jQuery.ajax to POST the content of the form to a custom PHP page that uses Factory::getMailer to actually send the e-mail.

Maybe it's convoluted, but it works.

After updating the site from Joomla3 to Joomla4, it stopped working.

The code is the exact same as in this question I posted a while ago:

//_JEXEC must be 1 or require_once requests will fail because of their "_JEXEC or die"
define('_JEXEC', 1);

//Then I need to require some Joomla! files where getMailer is defined
define('JPATH_BASE', __DIR__);
require_once (JPATH_BASE.'/includes/defines.php');
require_once ('includes/framework.php');

try {
    //fetching variables from querystring
    $name=$_POST['name'];
    $body=$_POST['body'];
    $from=$_POST['from'];
    //invoke mailer
    $mail = \Joomla\CMS\Factory::getMailer();
    $mail->setSender('[email protected]');
    $mail->addRecipient('[email protected]');
    $mail->setFrom($from,$name); # who is it?
    $mail->addReplyTo($from,$name); # who do I reply to?
    $mail->setSubject('E-mail from Firefighter\'s form');
    $mail->setBody($body);
    $mail->ClearCCs();
    $mail->ClearBCCs();
    $mail->ClearAttachments();
    $mail->ClearCustomHeaders();
    $mail->Send();
    echo "Mail sent";
    exit;
}
catch (Exception $e) {
    echo $e->getMessage();
}

Some considerations:

  • I restored a Joomla3 backup and it works, so I don't think it is a problem with PHPmailer versions
  • I have checked with the hosting and they are not blocking any e-mails this time (last time, they were the cause of the problem)

Testing and debugging

  • I have had the host activate php debugging and it doesn't log anything.
  • I have activated Joomla4's maximum level of error reports and nothing shows up.
  • I have placed an echo command right before Send(), and I get that right before the "failed to start application" from the catch echo.
  • Commenting out $mail->Send(); and nothing else echoes "Mail sent", as expected (of course, the mail is not sent).
  • Joomla's test e-mail works correctly.

So, everything works properly but the Send() function


I have not had time yet to check the following:

Just before the catch structure:

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

Adding $mail->isHtml(true);

Adding $mail->SMTPDebug = 2; (or 3)


I don't know if it's related to my problem (after all, I have not changed those settings in the last few weeks) but here are the settings, translated back from my language:

E-mail sending: yes Disable user e-mail sending: no Email from: [the mail I use for ftp access] Sender name: Firefighter's company's page Reply to e-mail: Reply to name: E-mail function: PHP mail

The question

How do I make my mailer work again?

1 Answer 1

2

The "Failed to start application" exception is thrown by \Joomla\CMS\Factory::getApplication(), which is called by \Joomla\CMS\Mail\Mail::Send()

The problem is because the appliocation object has not been set within the Factory.

The code that you have used to initiate a Joomla application works for version 3, but needs to be updated for version 4

Replace the code before your try/catch block with the following block and the script should work. (Code taken and stripped down from <JoomlaRoot>/index.php and <JoomlaRoot>/includes/app.php)

define('_JEXEC', 1);
define('JPATH_BASE', __DIR__);
require_once JPATH_BASE . '/includes/defines.php';
require_once JPATH_BASE . '/includes/framework.php';

$container = \Joomla\CMS\Factory::getContainer();
$container->alias('session.web', 'session.web.administrator')
    ->alias('session', 'session.web.administrator')
    ->alias('JSession', 'session.web.administrator')
    ->alias(\Joomla\CMS\Session\Session::class, 'session.web.administrator')
    ->alias(\Joomla\Session\Session::class, 'session.web.administrator')
    ->alias(\Joomla\Session\SessionInterface::class, 'session.web.administrator');

$app = $container->get(\Joomla\CMS\Application\AdministratorApplication::class);

\Joomla\CMS\Factory::$application = $app;
2
  • This works but I'm curious. I don't find any documentation that says that now you have to create all those aliases, how does one know that they have to do this if not by looking at similar files? Commented Jun 14, 2023 at 10:18
  • TBH I copied the parts from the core files that made it work. without the aliases, it didn't work, so I included them. The note in app.php says "Alias the session service keys to the web session service as that is the primary session backend for this application. In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered deprecated to be removed when the class name alias is removed as well." Commented Jun 15, 2023 at 11:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.