Skip to content

yii1tech/mailer

Repository files navigation

Symfony Mailer Extension for Yii 1


This extension provides integration of Symfony Mailer in the Yii1 application.

For license information check the LICENSE-file.

Latest Stable Version Total Downloads Build Status

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist yii1tech/mailer

or add

"yii1tech/mailer": "*"

to the "require" section of your composer.json.

Usage

This extension provides integration of Symfony Mailer in the Yii1 application. Application configuration example:

<?php

return [
    'components' => [
        'mailer' => [
            'class' => yii1tech\mailer\Mailer::class,
            'dsn' => 'smtp://user:pass@smtp.example.com:25',
        ],
    ],
    // ...
];

Note: please refer to the Symfony Mailer Manual for the instructions regarding the transport DSN specification.

Usage example:

<?php

use Symfony\Component\Mime\Email;

$email = (new Email())
    ->addFrom('noreply@example.com')
    ->addTo('johndoe@example.com')
    ->subject('Greetings')
    ->text('Welcome to our application')
    ->html('<h1>Welcome to our application</h1>');

Yii::app()->mailer->send($email);

Configuring Emails Globally

In order to simplify the code and avoid its duplication, you can set the default headers, which should be applied for each sending email. Application configuration example:

<?php

return [
    'components' => [
        'mailer' => [
            'class' => yii1tech\mailer\Mailer::class,
            'defaultHeaders' => [
                'From' => 'My Application<noreply@example.com>',
                'Bcc' => 'test-via-bcc@example.com',
                'X-Custom-Header' => 'foobar',
            ],
            // ...
        ],
    ],
    // ...
];

Template rendering

You may specify the content for the email body to be a result of rendering a particular view templates. It works in the similar way as rendering the views in your Web controllers. You'll need to use \yii1tech\mailer\TemplatedEmail in order to specify the templates.

<?php

use yii1tech\mailer\TemplatedEmail;

$email = (new TemplatedEmail())
    ->addFrom('noreply@example.com')
    ->addTo('johndoe@example.com')
    ->subject('Greetings')
    ->textTemplate('greetings-text') // Text Body will be set as render of 'views/mail/greetings-text.php'
    ->htmlTemplate('greetings-html') // HTML Body will be set as render of 'views/mail/greetings-html.php'
    ->context([
        'name' => 'John Doe', // variables, which will be available inside the templates
    ]);

Yii::app()->mailer->send($email); // actual rendering takes place just before the sending

By default, the view templates will be searched in the directory "views/mail" in the application base path. But you may configure \yii1tech\mailer\Mailer::$view component to use a different folder. You can also set a global layout for all template rendering. Application configuration example:

<?php

return [
    'components' => [
        'mailer' => [
            'class' => yii1tech\mailer\Mailer::class,
            'view' => [
                'viewPath' => dirname(__DIR__) . '/views/mail',
                'layout' => 'default-layout',
            ],
            // ...
        ],
    ],
    // ...
];

Inside the template file the following variables are always accessible:

  • $this - reference to \yii1tech\mailer\View instance.
  • $_message - reference to email message instance, which is rendered.

Template example:

<?php
/**
 * @var $this \yii1tech\mailer\View
 * @var $_message \yii1tech\mailer\TemplatedEmail
 * @var $name string
 */
 
$_message->subject('Email subject defined within the template');

$this->layout = 'particular-layout';
?>
<h1>Greetings</h1>
<p>Context var "name" = <?php echo CHtml::encode($name); ?></p>

<a href="<?php echo $this->createAbsoluteUrl('mail/unsubscribe', ['email' => $_message->getTo()[0]->getAddress()]); ?>">Unsubscribe</a>

Writing unit tests

You can use \yii1tech\mailer\transport\ArrayTransport while writing unit tests for your application. This transport will store all incoming email messages inside the internal field instead of actual sending them. Application configuration example:

<?php

return [
    'components' => [
        'mailer' => [
            'class' => yii1tech\mailer\Mailer::class,
            'dsn' => 'array://',
            // ...
        ],
    ],
    // ...
];

Unit test example:

<?php

use Symfony\Component\Mime\Email;

class MailTest extends TestCase
{
    public function testMail(): void
    {
        // code under test here

        /** @var \yii1tech\mailer\transport\ArrayTransport $transport */
        $transport = Yii::app()->mailer->getTransport();
        
        // retrieve the last sent email message:
        $sentMessage = $transport->getLastSentMessage();
        
        $this->assetNotNull($sentMessage);
        $this->assertSame('johndoe@example.com', $sentMessage->getTo()[0]->getAddress());
        // ...
        
        // retrieve the all sent email messages. matching the callback condition:
        $messages = $transport->filterSentMessages(function (Email $message) {
            return $message->getSubject() === 'Greetings';
        });
        $this->assertCount(1, $messages);
        // ...
    }
}