yiisoft/yii2-symfonymailer

Send email return TRUE but no mail sent

FedericoBenedetti1976 opened this issue · 16 comments

What steps will reproduce the problem?

What's expected?

What do you get instead?

Additional info

Q A
Yii version 2.0.42.1
Yii SymfonyMailer version 2.0.3
SymfonyMailer version ^5.4
PHP version 7.4.29
Operating system ubuntu 18.04

If i change transport settings, always ->send() return true, also if i set xxx.xxx.xx. as host

this is my code in console.php

        'mailer' => [
            'class' => 'yii\symfonymailer\Mailer',
            'transport' => [
                'scheme' => 'smtps',
                'host' => 'shout01.ot-mail.it',
                'username' => 'xxx',
                'password' => 'xxx',
                'port' => 465,
                'options' => ['ssl' => true],
                'dsn' => 'native://default',
            ],
            'viewPath' => '@app/mail/layouts/html_vuoto',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure transport
            // for the mailer to send real emails.
            'useFileTransport' => false,
        ],

this is my code in controller to test:

$from   = [ "xxxtest@gmail.com" => "Test"];
$to     = "anotheremail@gmail.com";
$sub    = "Test email sender"; 
$body = "this is a test";
$mailer = \Yii::$app->mailer;
        $message  = $mailer->compose('@app/mail/mail_base', compact("body"));
        $message->setFrom($from);
        $message->setTo($to);
        $message->setSubject($sub);
 $ret = $message->send();

// $ret is always TRUE also i insert any host address that doesn't exist. But no mail was sent. If i put useFileTransport=true, the email was wrtitten into file correctly

Likely that means that shout01.ot-mail.it accepted it without problems but did not sent it or that DKIM/SPF on that server aren't set correctly so there's delivery problem.

The problem is that if i try:

        'mailer' => [
            'class' => 'yii\symfonymailer\Mailer',
        ],

without transport settings, i have back TRUE too

We return false if the underlying library is failing for whatever reason. Looks like in your case it does not.

i'm debugging native code and i find this on BaseMailer.php

       ..
        if (array_key_exists('dsn', $config)) {
            $transport = $transportObj->fromString($config['dsn']);
        } elseif(array_key_exists('scheme', $config) && array_key_exists('host', $config)) {
            $dsn = new Dsn(
                $config['scheme'],
                $config['host'],
                $config['username'] ?? '',
                $config['password'] ?? '',
                $config['port'] ?? '',
                $config['options'] ?? [],
            );
           ..

So probably if you set Transport param "dns" it doesn't take your host/username/password/port/etc.. params
But in the official README.md Example there are all params together: https://github.com/yiisoft/yii2-symfonymailer#usage

During implementation, I tried to maintain backward compatibility with the yiisoft/yii2-swiftmailer. Perhaps it was wrong and it was necessary to move forward. If you are using DSN, then the password must be contained in it.

Note that if you don't specify a transport, a default NullTransport is used and no email is actually being sent. This is different from yiisoft/yii2-swiftmailer that defaults to Sendmail.

nd4c commented

Likely that means that shout01.ot-mail.it accepted it without problems but did not sent it or that DKIM/SPF on that server aren't set correctly so there's delivery problem.

I have a similar if not same problem, trying to use the smtp or smtps transport. Neither will work correctly. Does the Symfony Mailer expect to have message bus or something?

I set up my config to be able to switch between Swift or Symfony with appropriate settings. Swift works fine, Symfony does not return false, but I don't get the emails.

So I tried using a completely fake host and, again, it does not return false.

Please note that I am extending the \yii\symfonymailer\Mailer and \yii\symfonymailer\Message - but I do the same with Swift. They are very "thin" and are extended to handle changing the "to" for testing and to add in "useDisplayTransport".

The useFileTransport and useDisplayTransport work fine for both Swift and Symfony.

nd4c commented

@ FedericoBenedetti1976

You are correct. If there is a 'dsn' key in the transport config, then the rest is ignored. So either use a 'dsn' or set up the transport with the proper 'scheme', 'host', etc.

Also, note that the 'scheme' is used by Symfony to choose which Transport Factory to use. 'smtp' and 'smtps' will use the EsmtpTransportFactory to create an EsmtpTransport.

nd4c commented

https://github.com/yiisoft/yii2-symfonymailer/blob/master/src/Mailer.php#L213

The "Exception" from Symfony is a Throwable:
namespace Symfony\Component\Mailer\Exception;
/**
* Exception interface for all exceptions thrown by the component.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface ExceptionInterface extends \Throwable
{
}

But I have added in a catch for \Throwable and it doesn't work either. Even with a dummy host.

EDIT: It turns out the real problem was with extending the Mailer class and not copying over the needed private properties. I believe catch \Exception will work fine.

nd4c commented

$this->getSymfonyMailer()->send($message); is supposed to return a SentMessage object. But when I put in code to inspect that - the code is never reached as far as I can tell. ->send() never returns...

I do not have the debug module set up - so I turned that on. And I added in a finally block.

Debug shows the entry for "app\domain\email\symfony\Mailer::send" as 0ms, followed by code in the Controller afterAction method.

So apparently the try catch finally block is never completed - the action handler ends. Again, this seems to indicate that ->send() never returns.

nd4c commented

So far I've traced this to the get method for $this->encryptor - it's not returning. The code never gets to the try catch...

In Mailer sendMessage:
$message = $message->getSymfonyEmail();
if ($this->encryptor !== null) {
$message = $this->encryptor->encrypt($message);
}

$this->encryptor will return NULL in the yii\symfonymailer\Mailer. But if I extend that class then $this->encryptor does not return. Arrgghhh! It's set to private. I really like classes that are open for extension, but closed for modification...

So I had to copy the private members - will continue with test.

nd4c commented

Symfony is working for me. So my problem was trying to extend the Mailer class without copying the private members that are needed for the sendMessage method.

I'm not sure why the Mailer would be extended though, I'm skeptical it's the right approach.

Regardless, I think this can be closed right?

nd4c commented

Yes. Sorry for not getting back to this sooner. It was resolved by your pull request, "Code cleanup." Thanks for all your work on this!