Call to a member function has() on null in Drupal\Core\Mail\Plugin\Mail\PhpMail->mail()

Created on 7 July 2023, over 1 year ago
Updated 13 October 2023, about 1 year ago

Problem/Motivation

Error: Call to a member function has() on null in Drupal\Core\Mail\Plugin\Mail\PhpMail->mail() (line 114 of core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php).
Drupal\mailsystem\Adapter->mail(Array) (Line: 307)
Drupal\Core\Mail\MailManager->doMail('reroute_email', 'test_email_form', 'reniersediego@prometsource.com', 'en', Array, NULL, 1) (Line: 180)
Drupal\Core\Mail\MailManager->Drupal\Core\Mail\{closure}() (Line: 583)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 181)
Drupal\Core\Mail\MailManager->mail('reroute_email', 'test_email_form', 'reniersediego@prometsource.com', 'en', Array, NULL, 1) (Line: 70)
Drupal\mailsystem\MailsystemManager->mail('reroute_email', 'test_email_form', 'reniersediego@prometsource.com', 'en', Array) (Line: 191)
marquettelaw_custom_form_alter(Array, Object, 'reroute_email_test_email_form') (Line: 545)
Drupal\Core\Extension\ModuleHandler->alter('form', Array, Object, 'reroute_email_test_email_form') (Line: 840)
Drupal\Core\Form\FormBuilder->prepareForm('reroute_email_test_email_form', Array, Object) (Line: 284)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 583)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 166)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 74)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Steps to reproduce

Run

\Drupal::service('plugin.manager.mail')->mail('reroute_email', 'test_email_form', 'reniersediego@prometsource.com', 'en',
    [
      'cc' => '',
      'bcc'=> '',
      'subject' => 'test',
      'body' => 'test'
    ]);

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

🐛 Bug report
Status

Needs work

Version

10.1

Component
Mail 

Last updated 16 days ago

No maintainer
Created by

🇵🇭Philippines _renify_ cebu

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

  • Issue created by @_renify_
  • 🇵🇭Philippines _renify_ cebu

    $this->request seems has null value.

  • Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update over 1 year ago
    Not currently mergeable.
  • @_renify_ opened merge request.
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MariaDB 10.3.22
    last update over 1 year ago
    29,438 pass, 1 fail
  • Status changed to Needs work over 1 year ago
  • 🇺🇸United States tr Cascadia
    -    if (!$this->request->server->has('WINDIR') && !str_contains($this->request->server->get('SERVER_SOFTWARE'), 'Win32')) {
    +    if (!\Drupal::request()->server->has('WINDIR') && !str_contains(\Drupal::request()->server->get('SERVER_SOFTWARE'), 'Win32')) {

    I don't see how this can possibly do anything. The constructor already sets
    $this->request = \Drupal::request();

    Your patch is basically a regression of some of the work done in 🐛 Uncaught RfcComplianceException when email From name contains a comma Fixed .

  • 🇵🇭Philippines _renify_ cebu

    $this->request->server has null value even if its already on constructor. Seems wierd behaviour on my end.

  • 🇮🇳India swatichouhan012

    HIi _renify_

    To change the services with Global Service not good practice , i tried to replicate using a custom call but not got getting the mentioned error, would be great if you an provide more info the process you followed.

    Thanks

  • 🇧🇩Bangladesh linkanp

    #2 Patch worked for me. Thanks

  • Status changed to Postponed: needs info about 1 year ago
  • 🇺🇸United States tr Cascadia

    @linkanp: Please provide directions for reproducing this error.

    The steps in the issue summary do not cause an error for me or for the poster in #6.

  • Issue was unassigned.
  • Status changed to Needs review about 1 year ago
  • 🇨🇦Canada joelpittet Vancouver

    @TR I'll try to boil down the steps to reproduce but currently this is happening using the following modules:

    1. Drupal 10.1 (of course) just upgraded from 9.5
    2. monolog
    3. mimemail and mailsystem
    4. Our custom integration module https://github.com/ubc-cpsc/ubccs_monolog (but doesn't show in callstack so probably not part of it)

    To reproduce it we have an error in our code and it is going to email it to us with monolog -> mimemail
    Callstack:

    Error: Call to a member function has() on null in Drupal\Core\Mail\Plugin\Mail\PhpMail->mail() (line 114 of /var/www/html/public/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php).
    
    Drupal\Core\Mail\Plugin\Mail\PhpMail->mail(Array) (Line: 50)
    Drupal\mailsystem\Adapter->mail(Array) (Line: 307)
    Drupal\Core\Mail\MailManager->doMail('monolog', 'default', 'REDACTED@example.org', 'English', Array, NULL, 1) (Line: 180)
    Drupal\Core\Mail\MailManager->Drupal\Core\Mail\{closure}() (Line: 592)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 181)
    Drupal\Core\Mail\MailManager->mail('monolog', 'default', 'REDACTED@example.org', 'English', Array, NULL, 1) (Line: 70)
    Drupal\mailsystem\MailsystemManager->mail('monolog', 'default', 'REDACTED@example.org', 'English', Array) (Line: 58)
    Drupal\monolog\Logger\Handler\DrupalMailHandler->send('WARNING
    Message:
    Warning: Attempt to read property "server" on null in Drupal\Core\Mail\Plugin\Mail\PhpMail->mail() (line 114 of /var/www/html/public/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php) #0 /var/www/html/public/core/includes/bootstrap.inc(164): _drupal_error_handler_real(2, 'Attempt to read...', '/var/www/html/p...', 114)
    #1 /var/www/html/public/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php(114): _drupal_error_handler(2, 'Attempt to read...', '/var/www/html/p...', 114)
    #2 /var/www/html/public/modules/contrib/mailsystem/src/Adapter.php(50): Drupal\Core\Mail\Plugin\Mail\PhpMail->mail(Array)
    #3 /var/www/html/public/core/lib/Drupal/Core/Mail/MailManager.php(307): Drupal\mailsystem\Adapter->mail(Array)
    #4 /var/www/html/public/core/lib/Drupal/Core/Mail/MailManager.php(180): Drupal\Core\Mail\MailManager->doMail('monolog', 'default', 'REDACTED@example.org', 'English', Array, NULL, true)
    #5 /var/www/html/public/core/lib/Drupal/Core/Render/Renderer.php(592): Drupal\Core\Mail\MailManager->Drupal\Core\Mail\{closure}()
    #6 /var/www/html/public/core/lib/Drupal/Core/Mail/MailManager.php(181): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
    #7 /var/www/html/public/modules/contrib/mailsystem/src/MailsystemManager.php(70): Drupal\Core\Mail\MailManager->mail('monolog', 'default', 'REDACTED@example.org', 'English', Array, NULL, true)
    #8 /var/www/html/public/modules/contrib/monolog/src/Logger/Handler/DrupalMailHandler.php(58): Drupal\mailsystem\MailsystemManager->mail('monolog', 'default', 'REDACTED@example.org', 'English', Array)
    #9 /var/www/html/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php(61): Drupal\monolog\Logger\Handler\DrupalMailHandler->send('<h1 style="back...', Array)
    #10 /var/www/html/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php(44): Monolog\Handler\MailHandler->write(Object(Monolog\LogRecord))
    #11 /var/www/html/vendor/monolog/monolog/src/Monolog/Logger.php(379): Monolog\Handler\AbstractProcessingHandler->handle(Object(Monolog\LogRecord))
    #12 /var/www/html/vendor/monolog/monolog/src/Monolog/Logger.php(567): Monolog\Logger->addRecord(Object(Monolog\Level), '%type: @message...', Array)
    #13 /var/www/html/public/modules/contrib/monolog/src/Logger/LoggerInterfacesAdapter.php(134): Monolog\Logger->log(Object(Monolog\Level), '%type: @message...', Array)
    #14 /var/www/html/public/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(70): Drupal\monolog\Logger\LoggerInterfacesAdapter->log(3, '%type: @message...', Array)
    #15 /var/www/html/public/core/lib/Drupal/Core/EventSubscriber/ExceptionLoggingSubscriber.php(97): Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onError(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent))
    #16 [internal function]: Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onException(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
    #17 /var/www/html/public/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
    #18 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(240): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ExceptionEvent), 'kernel.exceptio...')
    #19 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(91): Symfony\Component\HttpKernel\HttpKernel->handleThrowable(Object(Drupal\Core\Entity\Query\QueryException), Object(Symfony\Component\HttpFoundation\Request), 1)
    #20 /var/www/html/public/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #21 /var/www/html/public/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #22 /var/www/html/public/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #23 /var/www/html/public/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #24 /var/www/html/public/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #25 /var/www/html/public/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #26 /var/www/html/public/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #27 /var/www/html/public/core/lib/Drupal/Core/DrupalKernel.php(704): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #28 /var/www/html/public/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
    #29 {main}.
    
  • Status changed to Needs work about 1 year ago
  • 🇺🇸United States smustgrave

    Don't think there is anything to review, Will need a test case showing this issue in core though.

    Also don't think we should be undoing the dependency injection.

  • 🇨🇦Canada joelpittet Vancouver

    I tried to set a breakpoint in the constructor, but it never hit that breakpoint there for some reason... which explain why it's not set, but I'm confused as to why/how/when it can be created without calling that.

    I'm using DDEV btw, restarted it, and rebuilt cache to try to get it to break there.

    @smustgrave I agree with your assessment in #10 in all counts, thanks for chiming in.

  • 🇺🇸United States tr Cascadia

    That error seems to come from $this->request being NULL in PhpMail when it tries to get $this->request->server

    The request is obtained in the PhpMail constructor:

       /**
         * PhpMail constructor.
         */
        public function __construct() {
            $this->configFactory = \Drupal::configFactory();
            $this->request = \Drupal::request();
        }

    That tells me that perhaps this is being called in a non-request context?

    Regardless, the problem is the lack of a request object. I still don't see how the patch in #2 can be doing anything at all if this is a problem with the global \Drupal::request() not containing a request object.

    I guess the first thing I would do here is to change PhpMail to implement ContainerFactoryPluginInterface and do the injection the normal way, rather than using \Drupal::request() in the constructor (was there some reason for that in the first place?. And in fact, I believe current best practice is to inject the request stack instead. See https://mglaman.dev/blog/dependency-injection-anti-patterns-drupal

    Still, this needs a test case - it's not clear why it's failing for you, and the instructions to reproduce in the issue summary aren't sufficient to narrow down the cause.

    Note that \Drupal::request() was added to PhpMail pretty recently, in 🐛 Uncaught RfcComplianceException when email From name contains a comma Fixed , which may be why this problem is just showing up now. I don't see any discussion in that issue about injection, and the test case added in that issue didn't reveal any problems. That's why it would be important to have a test case here which could demonstrate the problem and prove the solution.

  • 🇨🇦Canada joelpittet Vancouver

    @TR I'm tracking it down (slowly) but I think mailsystem is creating an instance before it has the request instance.

    I agree with that idea of implementing ContainerFactoryPluginInterface, good idea!

  • Status changed to Postponed: needs info about 1 year ago
  • 🇨🇦Canada joelpittet Vancouver

    @TR, I see the problem for me (might be the same for the OP), I'll leave this for @_renify_

    The problem was that mimemail overwrote the constructor
    https://git.drupalcode.org/project/mimemail/-/blob/8.x-1.0-alpha5/src/Pl...

    But it has been fixed already in the dev branch
    https://git.drupalcode.org/project/mimemail/-/blob/8.x-1.x/src/Plugin/Ma...
    @TR since you are a maintainer maybe you'd consider cutting an alpha6?

    I'll move the the dev branch in the meantime.

  • 🇨🇦Canada joelpittet Vancouver

    Adding the related issue it was fixed in mimemail, thanks @TR for committing it!

  • Status changed to Needs work about 1 year ago
  • 🇺🇸United States tr Cascadia

    MimeMail now has a new release. Thanks for that suggestion.

    Still not sure if @_renify_ or @linkanp were using MimeMail or if they were encountering some other problem.

    I also still think it's a good idea to do the injection properly in the PhpMail constructor rather than just use the global function. The only reason MimeMail had to be fixed was because MimeMail plugin needed the injected service and had to override the parent PhpMail class which wasn't doing injection properly.

  • 🇨🇦Canada joelpittet Vancouver

    Thanks @TR for getting that release out! I hope that fixes for the others as well!

Production build 0.71.5 2024