Mailer initialization by documentation

If I read https://book.cakephp.org/4/en/core-libraries/email.html#creating-reusable-emails , it seems that I can immediately send an email after adding:

use Cake\Mailer\Mailer; in AppController.php

and in UsersController.php

public function sendEmail(){
$mailer = new Mailer(‘default’);
$mailer->setFrom([‘me@example.com’ => ‘My Site’])
->setTo(‘you@example.com’)
->setSubject(‘About’)
->deliver(‘My message’); }

This gives me Class ‘App\Controller\Mailer’ not found. This made me wondering about the right usage of use() and it raised two questions.
How does the file correctly access app\vendor\cakephp\cakephp\src\Mailer by Cake\Mailer\Mailer ?
And how can I test if the loading is done correctly? For now I was able to find the folder of the file and made sure Mailer.php is there, but if I add use Nonsense/ApplePie it doesn’t notice me something is missing.

But I am above all confused that the documentation does not give me any clues as a beginning user.

This is a basic namespace understanding issue. Putting the use statement in AppController.php does nothing whatsoever for UsersController.php, even though the class in the latter extends the class in the former. Your use statement needs to be included in any file that uses new Mailer.

I had tried that before, but I see the given error was then for Email::deliver('x@x.z', 'Subject', 'Message', ['from' => 'me@example.com']); , which seemed another quick solution.

So I should set up a connection to the mailserver now. Could not send email: mail(): Failed to connect to mailserver ? This was also not clear by the documentation (introduction requirements).

You will typically need to configure a transport in order to send mail. That’s where you define the host name, email address, password, etc.

So the documentation is misleading saying you can send email after loading Mailer. It also seems that SMTP is optional, but in the example it seems required since it displays the connection with an email server

// In config/app.php

‘EmailTransport’ => [
// Sample Mail configuration <–What does this part do? Is it possible to send an email without connecting to an external provider?
‘default’ => [
‘className’ => ‘Mail’,
],
// Sample SMTP configuration
‘gmail’ => [
‘host’ => ‘smtp.gmail.com’,
‘port’ => 587,
‘username’ => ‘my@gmail.com’,
‘password’ => ‘secret’,
‘className’ => ‘Smtp’,
‘tls’ => true
]
],

So far I understand the properties of ‘EmailTransport’ can be used as an argument for Mailer objects, so

$mailer = new Mailer('gmail');
$mailer->setFrom(['me@example.com' => 'My Site']) ***and this would not be needed anymore***
    ->setTo('you@example.com')
    ->setSubject('About')
    ->deliver('My message');

Below the documentation describes a way without using Mailer:

$message = new \Cake\Mailer\Message();

$message
->setFrom(‘admin@cakephp.org’)
->setTo(‘user@foo.com’)
->setBody(“I assume some texts here works without the $render”);

$transport = new \Cake\Mailer\Transport\MailTransport();
$result = $transport->send($message);

Does that also imply without connecting to an external mail provider? It is just really hard for me to understand what is necessary and what is optional, what is basic and what is advanced. From the introduction of the documentation it seems very simple, but it is unclear what following parts of the documentation are essential to make it work :\

Moreover, I edited the app.php and app_local.php, app_local.example.php with my corresponding mail credentials and port, but the application still refers to localhost and the default port.

Whether you can send mail via your local server or need to use SMTP to an external provider is a question about your local server setup, not about Cake. If you have a mail server set up locally, then that should work fine. If you don’t, then it’s clearly not going to work.

That is true. The documentation is about cake though and is not entirely clear, even if I know my external SMTP settings. I think I need to understand what is essential for Cake config to make it work. The mail server has a host, port, user, password, but I don’t know what the ‘class’ field does - as I only see the config field (e.g. ‘gmail’/‘default’) being used in the app code. Moreover, in the documentation example ‘class’ is stated with a string while the default in app.php has a field ‘className’ => MailTransport::class. (‘timeout’ is neither mentioned in the documentation, ‘url’ rather briefly, but I figure these are surely redundant compared to class.)

So I have created a config field (what is the proper word for this?) ‘extmail’ in app_local.php

'extmail'=> [
			'host'=>'mail.x.eu',
			'port'=>'587',
			'username' => 'x@x.eu',
			'password' => 'xxxx',
			'class'=>'Smtp',
		    		]

and adding this without actual using it in the app, gives me the error:

Argument 1 passed to Cake\Core\App::className() must be of the type string, null given, called in …\cakephp\debug_kit\src\Panel\MailPanel.php on line 58

Since I don’t understand the Cake Mailer, I don’t know what is wrong with my config.

You have created a transport called extmail. As per the link I gave previously, this needs to have className in it, not class. Can you explain where you’re getting the idea that just class might be useful there?

The default transport does not need to be left configured as using the Mail class, you can set it up to use SMTP to GMail or whatever you want. It’s special only in that it’s the transport that will be used if you don’t specify an alternate one when you are sending your mail.

To be honest I can’t give you an answer, I couldn’t find it back. I thought it was in one of the various config files. Sorry.

But what does the className do? Now my error is

Datasource class Smtp could not be found.

Again the documentation leaves me without instructions where and what to add to this Smtp class, if any.

BTW I had to configure in the app.php and not app_local.php, while I expected to use app_local.php (since I have the app local and adapted this file for the DB). Does this matter, is it possible and preferable to use app_local.php instead?

Datasource class? Sounds like you have this configuration in the wrong place. Needs to be in the EmailTransport portion of the configuration.

I have it like this in both app and app_local config:

'EmailTransport' => [
        'default' => [
...
        ],
		'ext'=> [
			'host'=>'mail.ext.eu',
			'port'=>'587',
			'username' => 'x@ext.eu',
			'password' => 'y',
			'className'=>'Smtp',
		
		]
    ]

With the error

Unknown email configuration “ext”.

This error message is about an unknown email configuration, not an unknown email transport. Looking at the code that generates this error message (looking at the Cake code is very often a good way to better understand things, and the specific text of a error message is a great thing to search on), it seems that the terms “email configuration” and “email profile” are interchangeable, or more completely “email configuration profile”. Profiles are defined in the Email section of the config file, and one of the things that you set in the profile is which transport to use.

1 Like

Thanks for your sharpness. Then, after all, it is as convenient as it looks from the start. But it’s thanks to your clear comments rather than the documentation which is a pity for the utility it provides :
I intertwined ‘defaults’ in the documentation code. Since there is no default Email config, I didn’t realize there could be a difference.

In the sample skeleton app, the app.php most definitely has a default Email config, which references the default transport. If you think there are areas of the documentation that can use improvement, they are all in Github as well, so you can suggest edits to them.