PHP: test email sending using Yii example

Remember that post http://radzserg.com/2013/06/06/how-do-i-send-emails-in-my-applications/ about sending emails from your applications?

It’s time to test your emails ;).

Ok, so what do we have  \Zend\Mail\Transport\File – ideal for testing. We won’t send emails, but save them as files. Then after some test executed we need to get last sent email and check content and header.

I’ve created a simple class for that.

<?php

namespace myproject\tests;

use Yii;

/**
 * Assumes that we use \Zend\Mail\Transport\File for tests
 * @package om\tests
 */
class LastSentEmail
{

    private $_content;
    private $_headers;

    public function __construct()
    {
        $files = glob(Yii::getPathOfAlias('path.where.you.save.emails') . "/ZendMail_*");
        if (empty($files)) {
            throw new \CException("Email wasn't sent");
        }
        $filePath = end($files);

        $emailContent = file_get_contents($filePath);

        $this->_parseEmailBody($emailContent);
    }

    public function contains($search)
    {
        return stripos($this->_content, $search) !== false;
    }

    public function subjectContains($search)
    {
        return stripos($this->_headers['subject'], $search) !== false;
    }

    public function getHeaders()
    {
        return $this->_headers;
    }

    public function getHeader($name)
    {
        return isset($this->_headers) ? $this->_headers[$name] : null;
    }

    public function getSubject()
    {
        return $this->getHeader('subject');
    }

    public function getBody()
    {
        return $this->_content;
    }

    private function _parseEmailBody($content)
    {
        $pos = 0;
        foreach (explode("\r\n", $content) as $line) {
            $pos += mb_strlen($line) + 2;
            if ($line == "") {
                break;
            }

            list($headerName, $headerValue) = explode(":", $line, 2);

            $this->_headers[strtolower($headerName)] = trim($headerValue);
        }
        $this->_content = substr($content, $pos);
    }

}

Although we need a  little trick here for \Zend\Mail\Transport\FileOptions this will help us to order files in correct order.

$fileOptions = new \Zend\Mail\Transport\FileOptions();
$fileOptions->setPath($this->saveEmailPath);
$fileOptions->setCallback(function ($transport) {
    list($usec, $sec) = explode(" ", microtime());
    $time = ((float)$usec + (float)$sec);
    return "ZendMail_{$time}.tmp";
});
self::$_transport = new \Zend\Mail\Transport\File($fileOptions);

That’s it. Let’s test.


$email = new LastSentEmail();
$this->assertContains('subject pattern', $email->getSubject());
$this->assertContains('body pattern', $email->getBody());

Leave a Reply

Your email address will not be published. Required fields are marked *