Sending Email with Zend Framework 2 Using Template
Sending a templated HTML email is a one-liner in some frameworks, but Zend Framework 2 ships no such helper, so you have to wire up the view renderer, the MIME message, and the transport yourself. This post walks through that setup.
Note: Zend Framework 2 has reached end of life. In 2019 the project moved to the Linux Foundation and was renamed Laminas; the
Zend\*classes shown below now live underLaminas\*(e.g.Laminas\Mail,Laminas\View). The technique is unchanged, so this post still applies once you swap the namespaces.
For comparison, here is the same task in Laravel, where a single Mail::send() call renders a view and mails it:
Mail::send("mails.reset", $data, function ($message) use ($email) {
$message
->from("noreply@infinitescript.com", "CourseOcean")
->subject("Reset Your Password");
$message->to($email);
});
Zend Framework 2 has no equivalent shortcut, so we build it in two steps: a view template for the email body (Step 1), and a function that renders the template and sends the message (Step 2).
Step 1: Create an Email Template
The example here is a password-reset email for CourseOcean, an online course platform I built. Create the email body as a standard .phtml view script in the views folder, for example /view/mails/reset.phtml. It is an ordinary view template: the <?=$this->username?>, <?=$this->email?>, and <?=$this->keycode?> placeholders are view variables that we populate when rendering it in Step 2.
The markup itself is just an ordinary HTML email (inline styles omitted below for brevity); what matters is where the placeholders go:
<table cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td>
<img src="https://lab.haozhexie.com/CourseOcean/img/logo.webp" alt="CourseOcean" />
</td>
</tr>
<tr>
<td>
We received a request to reset the password for your account,
<?=$this->username?>.<br /><br />
<!-- ... -->
<a
href="https://lab.haozhexie.com/CourseOcean/accounts/resetPassword?email=<?=$this->email?>&keycode=<?=$this->keycode?>"
>Reset your password</a
>
<!-- ... -->
</td>
</tr>
</tbody>
</table>
Step 2: Complete Sending Email Function
With the template ready, the sending function does four things: render the template to an HTML string, wrap that string in a MIME part marked as HTML, attach it to a mail message, and hand the message to a transport.
function sendResetPasswordEmail($username, $email) {
$keycode = $this->generateRandomString(32);
$view = new \Zend\View\Renderer\PhpRenderer();
$resolver = new \Zend\View\Resolver\TemplateMapResolver();
$resolver->setMap([
"mailTemplate" => __DIR__ . "/../../../view/mails/reset.phtml",
]);
$view->setResolver($resolver);
$viewModel = new ViewModel();
$viewModel->setTemplate("mailTemplate")->setVariables([
"username" => $username,
"email" => $email,
"keycode" => $keycode,
]);
$bodyPart = new \Zend\Mime\Message();
$bodyMessage = new \Zend\Mime\Part($view->render($viewModel));
$bodyMessage->type = "text/html";
$bodyPart->setParts([$bodyMessage]);
$message = new \Zend\Mail\Message();
$message
->addFrom("noreply@infinitescript.com", "CourseOcean")
->addTo($email)
->setSubject("Reset Your Password")
->setBody($bodyPart)
->setEncoding("UTF-8");
$transport = new \Zend\Mail\Transport\Sendmail();
$transport->send($message);
}
A few pieces are worth calling out:
PhpRenderer+TemplateMapResolverturn the.phtmlfile into a string. The resolver maps the logical name"mailTemplate"to the file on disk, so$view->render()knows what to load.ViewModelcarries the variables (username,email,keycode) into the template, where they surface as$this->usernameand so on.Zend\Mime\Partwithtype = "text/html"is what makes this an HTML email rather than plain text. Without the explicit MIME type, the body is sent astext/plainand the markup shows up as raw tags.Zend\Mail\Transport\Sendmailsends through the localsendmailbinary. Swap inZend\Mail\Transport\Smtpif you need to send through an SMTP server instead.
Conclusion
There is more boilerplate here than Laravel’s one-liner, but the pieces are reusable: keep the PhpRenderer setup in a helper and every templated email becomes a matter of picking a template and passing variables.
The Disqus comment system is loading ...
If the message does not appear, please check your Disqus configuration.