<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Developer Day &#187; mail testing integration functional phpunit</title>
	<atom:link href="http://www.thedeveloperday.com/tag/mail-testing-integration-functional-phpunit/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thedeveloperday.com</link>
	<description>Staying Curious</description>
	<lastBuildDate>Fri, 03 Feb 2012 12:03:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>PHPUnit email integration testing using Sendmail</title>
		<link>http://www.thedeveloperday.com/phpunit-email-integration-testing-using-sendmai/</link>
		<comments>http://www.thedeveloperday.com/phpunit-email-integration-testing-using-sendmai/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 20:54:01 +0000</pubDate>
		<dc:creator>Žilvinas Šaltys</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[mail testing integration functional phpunit]]></category>

		<guid isPermaLink="false">http://www.thedeveloperday.com/?p=614</guid>
		<description><![CDATA[One of the problems when doing functional or integration testing is testing that emails are being sent out with a correct header and body. One such scenario could be a controller action which sends a password reset confirmation email and redirects to another action. A common way to solve such a problem is to configure [...]]]></description>
			<content:encoded><![CDATA[<p>One of the problems when doing functional or integration testing is testing that emails are being sent out with a correct header and body. One such scenario could be a controller action which sends a password reset confirmation email and redirects to another action.</p>
<p>A common way to solve such a problem is to configure the local MTA to store the test emails on the file system. The following shows how this could be done using sendmail. First create a sendmail alias by editing a file located at /etc/mail/aliases and adding a line bellow other aliases:</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
test-mail:        &#8220;| cat > /tmp/test-mail&#8221;
</p></blockquote>
<p>This tells sendmail that all incoming emails to test-mail will be written (not appended) to /tmp/test-mail. Sendmail needs to be restarted for the changes to take effect.</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
sudo /etc/init.d/sendmail restart
</p></blockquote>
<p>Depending on the situation it may be necessary to add the user who is going to be reading emails (for example apache) to the mail group.</p>
<blockquote style="background: #444; color: #fff; padding-left: 2px;"><p>
sudo /usr/sbin/usermod -G mail apache
</p></blockquote>
<p>Now using PHP it should be possible to do this:</p>
<pre name="code" class="php:nogutter">
$ok = mail('test-mail', 'Hello world!', 'I am an email.');
var_dump($ok);
echo file_get_contents('/tmp/test-mail');
</pre>
<p>Further PHPUnit could be extended to add the following method to the base test case class:</p>
<pre name="code" class="php:nogutter">
public function assertEmail($attributes, $emailFilePath,
$message = '', $delta = 0, $maxDepth = 10,
$canonicalizeEol = FALSE, $ignoreCase = FALSE)
{
    $mailParser = new Company_Product_MailParser;
    $mailData = $mailParser->parseFile($emailFilePath);

    foreach ($attributes as $attribute => $value) {
        $constraint = new PHPUnit_Framework_Constraint_IsEqual(
            $mailData[$attribute], $delta, $maxDepth, $canonicalizeEol, $ignoreCase
        );
        $this->_test->assertThat($value, $constraint, $message);
    }

    if (is_file($emailFilePath) &#038;&#038; is_writable($emailFilePath)) {
        unlink($emailFilePath);
    }
}
</pre>
<p>The mail parser class name explains itself:</p>
<pre name="code" class="php:nogutter">
class Company_Product_MailParser
{
    public function parseFile($mailFilePath)
    {
        $emailBody = file_get_contents($mailFilePath);
        $attributes = array(
            'to' => '',
            'from' => '',
            'date' => '',
            'subject' => '',
            'body' => ''
        );

        foreach (array_keys($attributes) as $attribute) {
            if($attribute  == 'body') {
                if (preg_match("/\n\n(.*)/", $emailBody, $matches, PREG_OFFSET_CAPTURE)) {
                    $offset = $matches[1][1];
                    $attributes[$attribute] = quoted_printable_decode(substr($emailBody, $offset));
                }
            } else {
                if (preg_match("/" . ucfirst($attribute) . ": (.*)\n/", $emailBody, $matches)) {
                    $attributes[$attribute] = $matches[1];
                }
            }
        }

        return $attributes;
    }
}
</pre>
<p><strong>Important notice.</strong> Sendmail may not immediately send the email and it may take a few seconds for the file to appear. It may require you to add a sleep for a few seconds before the email file appears. If you find a way how it is possible to make sendmail send an email immediately please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thedeveloperday.com/phpunit-email-integration-testing-using-sendmai/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

