0

In cakephp3 I'm using debugkit. My goal is to create a new Mailer transport class which stores the outgoing emails in a database in order to prevent it to sent out when in debug mode.

I've placed my Transport class in

       src/Mailer/Transport/DbMailTransport.php

Followed this I've set this class as default Mailer transport.

Email::configTransport('default', [
 'className' => 'DbMail',
 'host' => '',
 'port' => false,
 'timeout' => false,
 'username' => '',
 'password' => '',
 'client' => null,
 'tls' => true,
 'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),            
]);

When trying to send an email I got the following error:

    Fatal error: Cannot declare class Cake\Mailer\Transport\DbMailTransport, because the name is already in use in /src/Mailer/Transport/DbMailTransport.php on line 0

After further digging in the code debugging the $_transportConfig I got the following variables:

array(1) {
  ["default"]=>
  array(11) {
    ["className"]=>
    string(17) "DebugKit.DebugKit"
    ["host"]=>
    string(0) ""
    ["port"]=>
    bool(false)
    ["timeout"]=>
    bool(false)
    ["username"]=>
    string(0) ""
    ["password"]=>
    string(0) ""
    ["client"]=>
    NULL
    ["tls"]=>
    bool(true)
    ["url"]=>
    NULL
    ["originalClassName"]=>
    string(6) "DbMail"
    ["debugKitLog"]=>
    object(ArrayObject)#184 (1) {
      ["storage":"ArrayObject":private]=>
      array(0) {
      }
    }
  }
}

So the className is "DebugKit.DebugKit" instead of "DbMail". After turning off DebugKit in the bootstrap.php I got the correct classname:

array(1) {
  ["default"]=>
  array(9) {
    ["className"]=>
    string(6) "DbMail"
    ["host"]=>
    string(0) ""
    ["port"]=>
    bool(false)
    ["timeout"]=>
    bool(false)
    ["username"]=>
    string(0) ""
    ["password"]=>
    string(0) ""
    ["client"]=>
    NULL
    ["tls"]=>
    bool(true)
    ["url"]=>
    NULL
  }
}

My transport class working as expected, saves the outgoing emails to the database, so clearly the debugkit causing problems. Any idea how to resolve the issue?

JayTee
  • 3
  • 2
  • Whenever receiving errors, please always post **the _complete_ error**, that is, **including the _full_ stacktrace** (ideally copied from the logs where it is available in a properly readable fashion)! Also show/describe the corresponding context, ie show/highlight the code that actually triggers the error, and please always mention your _exact_ CakePHP version (last line in `vendor/cakephp/cakephp/VERSION.txt`) - thanks! – ndm Aug 23 '17 at 14:58

1 Answers1

0

This is caused by the strange behaviour of the DebugKit. It stores the original Transport class name in the 'originalClassName' variable in the transport config. It then uses its own transport class to gain the information for the debug panel's mail tab, then tries to restore the original transport class, and this is the point where it fails. You can either try to unload the debugkit, or check if your transport class exists before declaring it in order to prevent multiple declarations. E.g.: in src/Mailer/Transport/DbMailTransport.php

if(!class_exists('DbMailTransport')){ class DbMailTransport extends AbstractTransport { .... } }

Oliver Hale
  • 168
  • 7
  • To me that sounds like something that should be fixed somewhere else, as composer should normally prevent any double includes. – ndm Aug 23 '17 at 14:58
  • Unloading DebugKit wasn't working, but wrapping my transport class around an if statment did the trick: if(!class_exists('\Cake\Mailer\Transport\DbMailTransport')){ class DbMailTransport extends AbstractTransport { } } – JayTee Aug 23 '17 at 15:00