Nette Documentation Preview

Sending E-mails

Almost every web application needs to send e-mails, whether it's newsletter or order confirmation. That's why the Nette Framework provides necessary tools. This tutorial will show you how to:

  • create e-mail
  • send it
  • add attachments
  • use templates in e-mails
  • create links

Installation:

composer require nette/mail

Creating & sending e-mails

Example of creating an e-mail using Nette\Mail\Message class:

use Nette\Mail\Message;

$mail = new Message;
$mail->setFrom('John <john@example.com>')
	->addTo('peter@example.com')
	->addTo('jack@example.com')
	->setSubject('Order Confirmation')
	->setBody("Hello, Your order has been accepted.");

All parameters must be encoded in UTF-8.

And sending:

use Nette\Mail\SendmailMailer;

$mailer = new SendmailMailer;
$mailer->send($mail);

In presenters and services, we don't create mailer manually, but we will require the service of type Nette\Mail\Mailer using DI.

In addition to specifying recipient with addTo(), it's possible to specify recipient of copy with addCc() and recipient of blind copy: addBcc(). In all these methods, including setFrom(), we can specify addressee in three ways:

$mail->setFrom('john.doe@example.com');
$mail->setFrom('john.doe@example.com', 'John Doe');
$mail->setFrom('John Doe <john.doe@example.com>');

HTML content can be defined using setHtmlBody() method:

$mail->setHtmlBody('<b>Sample HTML</b> <img src="background.gif">');

Embedded images

Embedded images can be inserted using $mail->addEmbeddedFile('background.gif'), but it is not necessary. Why? Because Nette Framework finds and inserts all files referenced in the HTML code automatically. This behavior can be supressed by adding false as a second parameter of the setHtmlBody() method.

If an HTML e-mail has no plain-text alternative, it will be automatically generated. And if it has no subject set, it will be taken from the <title> element.

If you want to set returnPath and the server still overwrites it, use $commandArgs:

$mailer->commandArgs = '-fmy@email.com';

Attachments

Adding attachments to the e-mail is simple. In order to attach a file, we use addAttachment method:

// attaches example.zip to the e-mail
$mail->addAttachment('path/to/example.zip');

// attaches new example.txt file with "Hello John!" in it
$mail->addAttachment('example.txt', 'Hello John!');

// attaches example.zip renamed to info.zip
$mail->addAttachment('info.zip', file_get_contents('path/to/example.zip'));

Can be sending e-mails even easier?

Templates

The real power comes in combination with Latte templating system:

$latte = new Latte\Engine;
$params = [
	'orderId' => 123,
];

$mail = new Message;
$mail->setFrom('John <john@example.com>')
	->addTo('jack@example.com')
	->setHtmlBody($latte->renderToString('email.latte', $params));

File email.latte:

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Order Confirmation</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Hello,</p>

	<p>Your order number {$orderId} has been accepted.</p>
</body>
</html>

Using in Nette Application

Latte template system at its base does not know the {link} macro or the n:href attribute (and some others, such as the filter translate). These are supplemented by the TemplateFactory class from the nette/application package in conjunction with the presenter. To be able to create links in the template email, let the TemplateFactory to create a template. A presenter we will replace with LinkGenerator object, which can create links. We pass both objects through the constructor and create a template in the createTemplate () method:

class MailSender
{
	/** @var Nette\Application\LinkGenerator */
	private $linkGenerator;

	/** @var Nette\Bridges\ApplicationLatte\TemplateFactory */
	private $templateFactory;

	public function sendEmail(): void
	{
		$template = $this->createTemplate();

		$template->name = $order->getName();
		$template->setFile(__DIR__ . '/email.latte');

		$mail = new Message;
		$mail->setHtmlBody($template->renderToString());
	}

	protected function createTemplate(): Nette\Application\UI\ITemplate
	{
		$template = $this->templateFactory->createTemplate();
		$template->getLatte()->addProvider('uiControl', $this->linkGenerator);
		return $template;
	}
}

In the template, link is created like in a normal template. All links create over LinkGenerator are absolute:

<a n:href="Presenter:action">Link</a>

DKIM

DKIM (DomainKeys Identified Mail) is a trustworthy email technology that also helps detect spoofed messages. The sent message is signed by the SMTP server with the private key of the sender's domain and this signature is stored in the email header. The recipient's server compares this signature with the public key stored in the domain's DNS records. By matching the signature, it is shown that the email actually originated from the sender's domain and that the message was not modified during the transmission of the message.

$options = [
	'domain' => 'nette.org',
	'selector' => 'dkim',
	'privateKey' => file_get_contents('../dkim/dkim.key'),
	'passPhrase' => '****',
	'testMode' => true,
];

$mailer = new Nette\Mail\SendmailMailer; // or SmtpMailer
$mailer->setSigner(new Nette\Mail\DkimSigner($options));
$mailer->send($mail);

Mailers

Mailer is class responsible for sending e-mails. You can also create your own mailer – it's a class implementing Nette\Mail\Mailer interface.

SendmailMailer

The default mailer is SendmailMailer which uses PHP function mail.

SmtpMailer

To send mail via the SMTP server, use SmtpMailer.

$mailer = new Nette\Mail\SmtpMailer([
	'host' => 'smtp.gmail.com', //  if not set, php.ini settings will be used
	'username' => 'franta@gmail.com',
	'password' => '*****',
	'secure' => 'ssl',
]);
$mailer->send($mail);

Apart from options above SmtpMailer also offers more customisation options:

  • port – If not set, will be guessed based on secure option: 465 for value ssl, 25 otherwise.
  • context – Allows to fine-grain connection according to SSL context options. Contains an array of individual options.
  • timeout – Timeout for SMTP connection
  • persistent – Use persistent connection
  • clientHost – Client designation

Many of these options can be set in the framework configuration directly.

FallbackMailer

It does not send email but sends them through a set of mailers. If one mailer fails, it repeats the attempt at the next one. If the last one fails, it starts again from the first one.

$mailer = new Nette\Mail\FallbackMailer([
	$smtpMailer,
	$backupSmtpMailer,
	$sendmailMailer
]);
$mailer->send($mail);

Other parameters in the constructor include the number of repeat and waiting time (in miliseconds).