Git Product home page Git Product logo

yii2-symfonymailer's Introduction

Yii Mailer Library - Symfony Mailer Extension


This extension provides a Symfony Mailer mail solution for Yii framework 2.0.

For license information check the LICENSE-file.

Latest Stable Version Total Downloads Build Status codecov static analysis type-coverage

Requirements

  • PHP 8.1 or higher.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist yiisoft/yii2-symfonymailer

or add

"yiisoft/yii2-symfonymailer": "~3.0.0"

to the require section of your composer.json.

Usage

To use this extension, simply add the following code in your application configuration:

return [
    //....
    'components' => [
        'mailer' => [
            'class' => \yii\symfonymailer\Mailer::class,            
            'transport' => [
                'scheme' => 'smtps',
                'host' => '',
                'username' => '',
                'password' => '',
                'port' => 465,
                'dsn' => 'native://default',
            ],
            'viewPath' => '@common/mail',
            // 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,
        ],
    ],
];

or

return [
    //....
    'components' => [
        'mailer' => [
            'class' => \yii\symfonymailer\Mailer::class,            
            'transport' => [
                'dsn' => 'smtp://user:[email protected]:25',
            ],
        ],
    ],
];

You can then send an email as follows:

Yii::$app->mailer->compose('contact/html')
     ->setFrom('[email protected]')
     ->setTo($form->email)
     ->setSubject($form->subject)
     ->send();

DI Container

The Mailer component will automatically use the DI container when it is available. This allows you to easily override the transport factory configurations or their dependencies.

Migrating from yiisoft/yii2-swiftmailer

To migrate from the deprecated yiisoft/yii2-swiftmailer to this extension you need to update the application config.

Swiftmailer default transport was the SendmailTransport, while with this extension it will default to a NullTransport (sends no mail). You can use the swiftmailer default like the following:

'mailer' => [
    'class' => yii\symfonymailer\Mailer::class,
    'transport' => [
        'dsn' => 'sendmail://default',
    ],
],

With this extension, you do not have an ability of directly setting timeout, or other configurations that were possible with Swiftmailer extension. The reason is, the underlying Symfony package defines its classes as final thereby discouraging inheritance and pushing towards composition.

To achieve timeout, for example (and other transport configurations supported), you will need to define factory class and override default transport factory you are interested to replace through Yii DI container definitions.

Below is an example that shows you how to ovveride timeout.

First define your custom factory class.

namespace app\utils;

use Symfony\Component\Mailer\Transport\Dsn;
use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
use Symfony\Component\Mailer\Transport\TransportFactoryInterface;
use Symfony\Component\Mailer\Transport\TransportInterface;
use yii\base\BaseObject;

final class CustomSmtpFactory extends BaseObject implements TransportFactoryInterface
{
    public float $timeout;

    public function create(Dsn $dsn): TransportInterface
    {
        $transport = $this->create($dsn);
        if ($transport instanceof SmtpTransport) {

            /** @var SocketStream $stream */
            $stream = $transport->getStream();
            $stream->setTimeout($this->timeout);
        }
        return $transport;
    }

    public function supports(Dsn $dsn): bool
    {
        return $dsn->getScheme() == 'smtp';
    }
}

Then in the root of web configuration, set the factory class in container definitions, thereby overriding the default class.

'container' => [
    'definitions' => [
        EsmtpTransportFactory::class => [
            'class' => \app\utils\CustomSmtpFactory::class,
            'timeout' => 143, //Configure it to your own timeout
        ],
        // ... other definitions
    ],
],

That is all you need to do. The extension should use your new class and its configuration settings.

Security implications of the DSN

While the DSN might seem like a simple way to allow user configurable mailer settings it should be noted that the sendmail transport allows for execution of local executables. If you need to have a user configurable DSN (which is easier to build and more powerful to use than creating a GUI) you should probably disable the sendmail transport. Any user who has the power to configure a DSN essentially has shell access to wherever the code is running.

Testing

Check the documentation testing to learn about testing.

yii2-symfonymailer's People

Contributors

arhell avatar bizley avatar hyncica avatar krakozaber avatar lav45 avatar marcovtwout avatar margori avatar mrmuminov avatar mtangoo avatar particleflux avatar samdark avatar sammousa avatar sohelahmed7 avatar swanty avatar terabytesoftw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yii2-symfonymailer's Issues

Restore `Message` from Symfony email

What steps will reproduce the problem?

$originalMessage = Yii::$app->mailer->compose()
    ->setFrom('[email protected]')
    ->setTo('[email protected]')
    ->setTextBody('Test')
    ->attach('/path/to/attachment.pdf')
    ->setSubject('Test');

 $email = $originalMessage->getSymfonyEmail();

 $restoredMessage = new yii\symfonymailer\Message(['email' => $email]);

What's expected?

A message can be succesfully restored from the source Symfony\Component\Mime\Email object.

What do you get instead?

An yii\base\UnknownPropertyException with the message Setting unknown property: yii\symfonymailer\Message::email.

What is the use-case?

An email queue that stores the message on disk. The Symfony email message can be serialized and stored on disk. However, when it is unserialized there is no way to restore the yii\symfonymailer\Message object and send it.

Additional info

Q A
Yii version 2.0.49.3
Yii SymfonyMailer version 2.0.4
SymfonyMailer version v6.4.4
PHP version 8.1.27
Operating system Debian

__sleep() added to Message class causes that subclass cannot be serialized

... and yii\base\ErrorException: serialize(): "email" returned as member variable from __sleep() but does not exist is shown instead.

It seems to be caused by the fact that 'email' item is returned from __sleep() method and corresponding $email property is private and is not accessible in subclasses. charset is the same case IMHO.

What steps will reproduce the problem?

  1. create subclass of yii\symfonymailer\Message
  2. serialize() object of subclass

What's expected?

Serialized object.

What do you get instead?

Error mentioned above.

Additional info

Q A
Yii version 2.0.48.1
Yii SymfonyMailer version 3.0.0
SymfonyMailer version 5.4.22
PHP version 7.4.33
Operating system Fedora Linux

cannot send email

Hi, I'm migrating from swiftmail to symfonymail.
This is the configuration:

        'mailer' => [
            'class' => \yii\symfonymailer\Mailer::class,
            'useFileTransport' => false,
            'messageClass' => 'app\components\MiaMessage',
            'transport' => [
                'scheme' => 'smtps',
                'host' => 'smtps.xxxx.xx',
                'username' => 'aaaaa',
                'password' => 'bbbbb',
                'port' => 25,
                'options' => [
                    'verify_peer' => 0,
                ],
            ],
            'viewPath' => '@app/mail',
        ],

When executing the “send” command, this is the error shown:

Symfony\Component\Mailer\Exception\TransportException
Connection could not be established with host "ssl://smtps.xxxx.xx:25": stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:1408F10B:SSL routines:ssl3_get_record:wrong version number

I can’t find any solution. Can someone helps me?
Thanks

[EDIT]
Suppressing the customized class MiaMessage and using the standard one, the behavior is the same.


Yii 2.0.48
yii2-symfonymailer 3.0.0
PHP 7.3.x

Release

What needs to be completed for the release ?

Improve documentation defaults when swapping from yii2-swiftmailer

When swapping from deprecated https://github.com/yiisoft/yii2-swiftmailer to this extension, two things needed to be changed to keep everything working as before:

  1. Swiftmailer default transport was the SendmailTransport, while this extension will default to a NullTransport (sends no mail). You can use the swiftmailer default by defining in application config:
'mailer' => [
    'class' => yii\symfonymailer\Mailer::class,
    'transport' => [
        'dsn' => 'sendmail://default',
    ],
],
  1. Codeceptions TestMailer specifies swiftmailer\Message as a default class in https://github.com/Codeception/module-yii2/blob/master/src/Codeception/Lib/Connector/Yii2/TestMailer.php#L8. This can also be changed by defining in test config:
'mailer' => [
    'class' => yii\symfonymailer\Mailer::class,
    'messageClass' => \yii\symfonymailer\Message::class,
],

Not sure if any of these should be a code change, but I thought it was useful to report and perhaps have it documented in the README.

Mailer->sendMessage Exception Bug

What steps will reproduce the problem?

[ ] In mailer config transport is set up with a "dummy" host.
This will cause a TransportException.
[ ] $message is set to a proper yii\symfonymailer\Message
[ ] $mailer is set to the yii\symfonymailer\Mailer

	try {
		$result = $mailer->send($message);
	} catch (\Throwable $e) {
		static::$errors[] = $e->getMessage();
	} catch (\Exception $e) {
		static::$errors[] = $e->getMessage();
	}

What's expected?

\Throwable should catch the TransportException.

What do you get instead?

No Throwable or Exception.
$result = false

Additional info

/**
 * {@inheritDoc}
 *
 * @throws TransportExceptionInterface If sending failed.
 */
protected function sendMessage($message): bool
{
    if (!($message instanceof Message)) {
        throw new RuntimeException(sprintf(
            'The message must be an instance of "%s". The "%s" instance is received.',
            Message::class,
            get_class($message),
        ));
    }

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

    if ($this->signer !== null) {
        $message = $this->signer instanceof DkimSigner
            ? $this->signer->sign($message, $this->dkimSignerOptions)
            : $this->signer->sign($message)
        ;
    }
    try {
        $this->getSymfonyMailer()->send($message);
  /*****  This catch will catch the TransportException  and then return false *****/
    } catch (\Exception $exception) {
        Yii::getLogger()->log($exception->getMessage(), \yii\log\Logger::LEVEL_ERROR, __METHOD__);
        return false;
    }
    return true;
}
Q A
Yii version 2.0.45
Yii SymfonyMailer version 2.0.3
SymfonyMailer version v6.0.11
PHP version 8.1.9
Operating system Linux Mint 20.3 with Kernel Linux 5.15.0-46-generic

No exception is thrown to caller when sending mail fails

Ref line:

return false;

This catch does not re-throw the exception and instead does its own logging and returns false. There should be a way to suppress this behavior and let the exception be caught by the caller.

I have my own logging setup and now I have no way of logging the actual exception the way I want to after upgrading from the old swiftwmailer component.

Additional info

Q A
Yii version
Yii SymfonyMailer version
SymfonyMailer version
PHP version
Operating system

Allow using a custom HttpClient

What steps will reproduce the problem?

Symfony is very opinionated and uses their own HttpClient implementation and interfaces.
Since there are perfectly fine PSR standards for this and other implementations of the Symfony HttpClientInterface exist, we should allow the user to configure it.

What's expected?

The Yii2 component should use the Yii2 DI container to retrieve dependencies, this allows for using configuration in the usual way.

What do you get instead?

I can't define my own http client configuration.

Proposed solution

Add a property public $httpClient = null and use it in the call to Transport::getDefaultFactories().

Implementation try catch for debugging

What steps will reproduce the problem?

What's expected?

What do you get instead?

Additional info

Q A
Yii version 2.0.45
Yii SymfonyMailer version 2.0.3
SymfonyMailer version >= 5.4.0
PHP version 7.4.20
Operating system Ubuntu 20.04

How to catch error when sending email. My problem is, when in localhost is success, but in production is failed.

 public function kirimEmailPengajuanLoginAccount($userYangMengajukanId): bool
    {
        $settings = Yii::$app->settings;
        $emailTo = $settings->get('Email.pengaktifanUserAccount');
        $senderEmail = $settings->get('Email.senderEmail');
        $senderName = $settings->get('Email.senderName');

        $userYangMengajukan = User::findOne($userYangMengajukanId);

        $mailer = Yii::$app->mailer->compose('pengajuan_user_account', [
            'model' => $this,
            'userYangMengajukan' => $userYangMengajukan
        ])
            ->setTo($emailTo)
            ->setFrom([$senderEmail => $senderName])
            ->setReplyTo($emailTo)
            ->setSubject('Permohonan pengaktifan user account atas nama: ' . $this->nama);

        try {
            return $mailer->send();
        } catch (TransportExceptionInterface $e) {
            $this->addError('nama', $e->getDebug());
        }

        return false;


    }

I got empty array in 'nama' attribute.
Thanks for the suggestion

Send email return TRUE but no mail sent

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

Working within queues support

What steps will reproduce the problem?

Trying to use yii2-symfonymailer in queue job.

What's expected?

Everything is working.

What do you get instead?

BadMethodCallException : Cannot serialize Symfony\Component\Mailer\Transport\Smtp\SmtpTransport
at
\vendor\symfony\mailer\Transport\Smtp\SmtpTransport.php:356

Additional info

At the current moment this extension can't be used in queue jobs (with https://github.com/yarcode/yii2-queue-mailer as example), because that jobs are serialized, but initialized Transport object prevents serialization. Deprecated yii2-swiftmailer extension has no such problem.
The reason is that, the Transport object is initializing directly in setter, if it passed as array configuration. It seems, that this behavior can be changed easily. This require just to remove Transport object initialization from setTransport() (it all be done in getTransport() anyway).
I prepared pull request, that demonstrates my idea, and this code perfectly works within queues. I did not remove the Transport initialization code from setter, in order to not to break current tests, but added a class variable to control the described behavior.

Readme Timeout Example does not work.

The example given to expand SymfonyMailer found in the read me setting a timeout with the example given (copying and pasting), throws error(s). I ended up doing a fresh install, of the newest version of Yii2 running on my development server (PHP 8.1)

The error:
Setting unknown property: yii\symfonymailer\Mailer::transportFactory

On my production server, I've attempted to setup Symfony mailer, once again copying and pasting the example code given to setup a timeout feature only to discover that Symfony mailer interferes with the Yii2 Log Email target, disabling this feature prevents the error:

PHP Warning: Attempt to read property “enabled” on array in /vendor/yiisoft/yii2/log/Dispatcher.php on line 190

I've posted about my struggles with Symfony mailer on the community forum https://forum.yiiframework.com/t/swiftmailer-to-symfonymailer-timeout-expansion-yii2-log-email-target/135773

Yii2 version: 2.0.49.3
Yii2 Symfony mailer version: v6.0.19
PHP version: 8.1

Dependency issues on 7.4

What steps will reproduce the problem?

I required yiisoft/yii2-symfonymailer (^3.0) but on PHP 7.4 I get:

  Problem 1
    - psr/log is locked to version 3.0.0 and an update of this package was not requested.
    - psr/log 3.0.0 requires php >=8.0.0 -> your php version (7.4.33) does not satisfy that requirement.
  Problem 2
    - symfony/mime is locked to version v6.3.2 and an update of this package was not requested.
    - symfony/mime v6.3.2 requires php >=8.1 -> your php version (7.4.33) does not satisfy that requirement.
  Problem 3
    - psr/log 3.0.0 requires php >=8.0.0 -> your php version (7.4.33) does not satisfy that requirement.
    - symfony/mailer v5.4.31 requires psr/log ^1|^2|^3 -> satisfiable by psr/log[3.0.0].
    - symfony/mailer is locked to version v5.4.31 and an update of this package was not requested.

What's expected?

v3 should work fine on 7.4.

Additional info

Q A
Yii version 2.0.41.1
Yii SymfonyMailer version
SymfonyMailer version
PHP version 7.4
Operating system Linux

Define a default transport / error without transport

A suggestion:

When switching from yii2-swiftmailer, there is a pitfall: You have to add a transport config option. The swiftmailer extension defaulted to sendmail transport:

https://github.com/yiisoft/yii2-swiftmailer/blob/master/src/Mailer.php#L175-L177

I think it would be a good idea to either add a sane default (sendmail or php setting?), or throw an error due to invalid config.

The main problem with this is that is just fails silently with no transport specified, even returning true on send(), suggesting that it has been successful, when it was not.

Logger proxy should be in separate repository

This library contains a proxy allowing us to provide a PSR LoggerInterface and route its output to Yii's logger.
This should be in the core or a separate library, it is a useful tool with and without symfony mailer.

I'm happy to create a PR if you can create a new repo, or to create a PR for the Yii2 core, but I think that's feature frozen. Of course I could make this in my own repository as well but it would be better if it lives in yiisoft.

Mailer re-enable TLS support after manual disable

What steps will reproduce the problem?

//I disabled work with tls support because I am connecting to localhost and I have a self-signed certificate installed on the mail server

$transport = new EsmtpTransport('localhost', 25, FALSE ); //third parameter equal to false disables tls support

$transport->setUsername( 'username' )
          ->setPassword( 'password' );

$mailer = new Mailer($transport);
$message = (new Email())->from( '[email protected]')
                        ->subject( 'subject' )
                        ->to('[email protected]')
                        ->text('body');
try {
    $mailer->send($message);
} catch (TransportException $e) {
   $lastErrorMsg = $e->getMessage();
} catch( \Throwable $e) {
   $lastErrorMsg = $e->getMessage();
} catch (\Exception $e) {
   $lastErrorMsg = $e->getMessage();
}

var_dump( $lastErrorMsg );
die();

What's expected?

Inside vendor\symfony\mailer\Transport\Smtp\EsmtpTransport.php source code

    protected function doHeloCommand(): void
    {
        if (!$capabilities = $this->callHeloCommand()) {
            return;
        }

        /** @var SocketStream $stream */
        $stream = $this->getStream();
        // WARNING: !$stream->isTLS() is right, 100% sure :)
        // if you think that the ! should be removed, read the code again
        // if doing so "fixes" your issue then it probably means your SMTP server behaves incorrectly or is wrongly configured
        if (!$stream->isTLS() && \defined('OPENSSL_VERSION_NUMBER') && \array_key_exists('STARTTLS', $capabilities)) {
            $this->executeCommand("STARTTLS\r\n", [220]);

            if (!$stream->startTLS()) {
                throw new TransportException('Unable to connect with STARTTLS.');
            }

            $capabilities = $this->callHeloCommand();
        }

        if (\array_key_exists('AUTH', $capabilities)) {
            $this->handleAuth($capabilities['AUTH']);
        }
    }

the following line of code causes that, despite the fact that I disabled tls earlier, if the mail server responds with tls support after the hello, the secure connection attempt will still continue. but it's correct, if I disabled tls support, then it should remain disabled, and the STARTTLS command should not be sent to the mail server

...
if (!$stream->isTLS() && \defined('OPENSSL_VERSION_NUMBER') && \array_key_exists('STARTTLS', $capabilities)) {
...

What do you get instead?

Error message:
Unable to connect with STARTTLS: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

Additional info

Q A
Yii version 2.0.47
Yii SymfonyMailer version 3.0.0
SymfonyMailer version 5.4
PHP version 7.4.30
Operating system Ubuntu (Server) 18.04.6 LTS

SES Failed to authenticate on SMTP server with username

in my composer.json i have this

"symfony/amazon-mailer": "^6.0",
"yiisoft/yii2-symfonymailer": "^2.0",

in my main.php i have this

 'mailer' => [
            'class' => \yii\symfonymailer\Mailer::class,
            'viewPath' => '@frontend/views/user/mail',
            'useFileTransport' => false,
            'transport' => [
                'dsn' => 'ses+smtp://XXXXXXXXXXX:'.urlencode('xxxxxxxxxxxxxxx').'@email-smtp.ap-southeast-1.amazonaws.com:587',
             ]
]

when i send an email using my contact from, this show up in my log files.

2022-06-14 13:40:53 [][-][-][error][yii\symfonymailer\Mailer::sendMessage] Failed to authenticate on SMTP server with username "XXXXXXXXXXX" using the following authenticators: "LOGIN", "PLAIN". Authenticator "LOGIN" returned "Expected response code "235" but got code "535", with message "535 Authentication Credentials Invalid".". Authenticator "PLAIN" returned "Expected response code "235" but got code "535", with message "535 Authentication Credentials Invalid".".
2022-06-14 13:40:49 [][-][-][info][application] $_GET = []

my username and password is correct, any idea what im missing? thanks.

Additional info

Q A
Yii version 2.0.45
Yii SymfonyMailer version ^2.0
SymfonyMailer version v6.0.8
PHP version 8.1.6
Operating system Ubuntu

Remove the `with`-mutators

In Yii components are mutable and factories are not used.
The primary use case for with functions are if you are given an object of a given interface and you want to transform it (either in a mutable or immutable fashion).

The functions withEncryptor, withSigner should probably be removed since in this case you could just make the properties public and typed.

Logs

It would be nice to add a logger

update irc link

What steps will reproduce the problem?

What's expected?

What do you get instead?

Additional info

Q A
Yii version
Yii SymfonyMailer version
SymfonyMailer version
PHP version
Operating system

update root folder links

What steps will reproduce the problem?

http=>https

What's expected?

What do you get instead?

Additional info

Q A
Yii version
Yii SymfonyMailer version
SymfonyMailer version
PHP version
Operating system

No Email sent, no error, send() returns true

What steps will reproduce the problem?

config/web.php :

$config = [
   ...
   'components' => [
      ...
      'mailer' => require(__DIR__ . '/mailer.php'),
      ...
   ],
   ...
]

config/mailer.php :

<?php

$params = require(__DIR__ . '/params.php');

return [
    'class' => \yii\symfonymailer\Mailer::class,
    'transport' => [
        'host' => 'smtp.gmail.com',
        'username' => $params['adminEmail'],
        'password' => '********',
        'port' => '465',
        'options' => ['ssl' => true],
    ],
    'messageConfig' => [
        'from' => $params['adminEmail'], //'bcc' => '<bbc email>',
    ],
];

Method to send email:

public function sendEmail() {
    $mailer = Yii::$app->mailer;
    $oldViewPath = $mailer->viewPath;
    $mailer->viewPath = "@app/mail";
    $isSent = $mailer->compose('testEmail')
                    ->setTo($this->email)
                    ->setSubject(Yii::t('dev', 'Email Test Send'))
                    ->send();
    
    $mailer->viewPath = $oldViewPath;
    return $isSent;
}

$this->email comes from a form

What's expected?

Email will be send. ->send() method returns true.

What do you get instead?

Email won't be send. -> send() method returns true.

Additional info

Q A
Yii version 2.0.44
Yii SymfonyMailer version 2.0.0
SymfonyMailer version 6.0.2
PHP version 8.0.13
Operating system Manjaro

I switched from yiisoft/yii2-swiftmailer": "~2.1.2 . Sending email with swiftmailer worked.
Do I miss additional configuration? As stated from my config I'm trying to send from/over gmail account.

Document TransportFactoryInterface: Adding Socket Timeout Option to Mailer

What steps will reproduce the problem?

Migrate from Swift Mailer to Symfony Mailer

What's expected?

SwiftMailer has a transport->timeout property that can be set in the config. Defaults to 30.

What do you get instead?

The Symfony Mailer does not have an exposed way to set the timeout for the EsmtpTransport. (There is a value and a setter Method, but there is no way to call it since the transport is private...)

Additional info

If the Symfony Transport timeout property is not set it will default to the php.ini setting, 'default_socket_timeout' which default to 60.

We can wrap the mailer->send() call, but it would be nice to be able to config the Mailer's timeout value.

We cannot add a new property to the transport itself, but we can add one to the yii Mailer class.

Possible solution:

class Mailer extends BaseMailer
 {
    /**
     * @var int transport_timeout defaults to 0 since this would only apply to smtp/smtps transports.
     */
    public $transport_timeout = 0;
    ...
    /**
     * {@inheritDoc}
     *
     * @throws TransportExceptionInterface If sending failed.
     */
    protected function sendMessage($message): bool
    {
        ...
        try {
            if (!empty($this->transport_timeout) && (int) $this->transport_timeout > 0) {
                $default_socket_timeout = ini_set('default_socket_timeout', (int) $this->transport_timeout);
            }
            $this->getSymfonyMailer()->send($message);
        } catch (\Exception $exception) {
            Yii::getLogger()->log($exception->getMessage(), \yii\log\Logger::LEVEL_ERROR, __METHOD__);
            // need to re-throw the exception so that caller can extract transport errors
            throw($exception);
        } finally {
            if (!empty($default_socket_timeout) && (int) $default_socket_timeout > 0) {
                ini_set('default_socket_timeout', (int) $default_socket_timeout);
            }
        }
        return true;
    }
}
Q A
Yii version 2.0.45
Yii SymfonyMailer version 2.0.3
SymfonyMailer version v6.0.11
PHP version 8.1.9
Operating system Linux Mint 20.3 with Kernel Linux 5.15.0-46-generic

Drop support for php 7.4 and 8.0

Both php 7.4 and 8.0 are EOL.

I propose dropping support for these versions (note that old code bases can happily use version 3.x of this library).

Can a default sendFrom address be called by updating the configuration file?

At the moment whenever we create a message we have to call setFrom() to set the send from address.

I understand the need for this but could we not have a fallback email - set in the mailer component - to use if setFrom() is not set.

For example a noreply@somedomain email configured at application level

Incorrect CID in embed()

What steps will reproduce the problem?

Try to embed any image in mail with display as an image. Simple example: logo in email template
image

What's expected?

The image is displayed in the right place

What do you get instead?

The image is only in the attachment to the letter but is not displayed

Additional info

Related to this issue #15

It seems CID is incorrect.
image

The problem seems to be that it is generated much later and is not immediately available. (screenshots from SymfonyMailer)
image

It seems, cid exist only in $part variable and it's available only inside the private method of body generation.
image

Perhaps the problem is just with SymfonyMailer. I still don't see how to get the real CID of the attachment and return it to the package's embed() function

Q A
Yii version 2.0.46
Yii SymfonyMailer version 2.0.3
SymfonyMailer version 6.1.3
PHP version 8.1
Operating system Win 11

Expose symfony mailer events

What steps will reproduce the problem?

Currently there is no way to hook on the Mailer Events

What's expected?

I expect to be able to set a Yii event for this, and be able to interact with Symfony Mailer prior to message sending, to inline CSS for example.

What do you get instead?

Nothing, and that's blocking me from switching from Swift Mailer.

Let's implement this after #27 gets finally merged.

Messy implementation of private $_transport

What steps will reproduce the problem?

Inspect the code; it is functional but the implementation is messy.

First of all note that the variable is private:

    /**
     * @var TransportInterface|array Symfony transport instance or its array configuration.
     */
    private $_transport = [];

This means the only way it ever gets set is via setTransport:

/**
     * @param array|TransportInterface $transport
     * @throws InvalidConfigException on invalid argument.
     */
    public function setTransport($transport): void
    {
        if (!is_array($transport) && !$transport instanceof TransportInterface) {
            throw new InvalidConfigException('"' . get_class($this) . '::transport" should be either object or array, "' . gettype($transport) . '" given.');
        }
        if ($transport instanceof TransportInterface) {
            $this->_transport = $transport;
        } elseif (is_array($transport)) {
            $this->_transport = $this->createTransport($transport);
        }

        $this->symfonyMailer = null;
    }

Looking at this code we can actually conclude that $this->_transport will never be an array.
In php 8.1 we could write it like this:

private TransportInterface $_transport;

public function setTransport(TransportInterface|array $transport): void
{
    $this->_transport = $transport instanceof TransportInterface ? $transport : $this->createTransport($transport);
}

Given that createTransport() always returns a created transport, or throws an exception we can be 100% sure that after a call to setTransport() we get either an exception or the transport was successfully created and set.

This means we can, and should remove getTransport() alternatively, at least we should simplify it:

public function getTransport(): TransportInterface
{
    return $this->_transport;
}

Last but not least, Yii uses a pattern where init() is called after configuration which means we should use it to test for correct configuration. This will throw an error closer to the error (on / after instantiation instead of on use)

public function init() {
    if (!isset($this->_transport)) {
        throw new InvalidConfigException("No transport configured");
    }
}

More examples

I think you need to add more examples for ppl migrating from swift to this mailer

I found out the default working configuration using PHP configured mailer is:

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

			'transport' => [
				'host' => '',
				'scheme' => 'smtps',
				'username' => '',
				'password' => '',
				//'port' => 465,
				//'options' => ['ssl' => true],
				'dsn' => 'native://default',
			],
			'viewPath' => '@common/mail',

			// send all mails to a file by default. You have to set
			// 'useFileTransport' to false and configure a transport
			// for the mailer to send real emails.
			'useFileTransport' => false,
		],

You cannot miss the host, scheme, dsn entries.

Failed to instantiate component or class "yii\symfonymailer\Mailer::class".

Hi, If I add :: class show the error:
Failed to instantiate component or class "yii\symfonymailer\Mailer::class".

but if I not use ::class work well
'class' => 'yii\symfonymailer\Mailer',

I belive that is need change in Readme.

By the way, I change from 'yii\swiftmailer\Mailer' to 'yii\symfonymailer\Mailer' and for the moment all work well, this is my changes:
With Swiftmailer;

	'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            'useFileTransport' => false,
            'transport' =>
                [
                    'class' => 'Swift_SmtpTransport',
                    'host' => 'email-smtp.eu-west-1.amazonaws.com',
                    'username' => '****',
                    'password' => '****',
                    'port' => '587',
                    'encryption' => 'tls',
                ]
        ],

and with Symfony:

'mailer' => [
            'class' => 'yii\symfonymailer\Mailer',
            'transport' =>
                [
                    'dsn' => 'ses+smtp://USERNAME:[email protected]',
                ]
        ],		

Remove tooling configs from distribution packages

I think these:

.editorconfig
captainhook.json
ecs.php
infection.json.dist

Should be added to the .gitattributes with the exclude-ignore tag.
They're useless in an installed production environment.

Additional info

Q A
Yii version -
Yii SymfonyMailer version 4.0.0
SymfonyMailer version -
PHP version -
Operating system -

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.