Mail

odesílání
emailů

Odesílání e-mailů

Téměř každá aplikace na webu potřebuje odesílat e-maily, ať už newslettery nebo potvrzení objednávky. Proto Nette Framework poskytuje potřebné nástroje. Naučime se:

  • jak e-mail vytvořit
  • jak ho odeslat
  • jak přidat přílohy
  • jak v e-mailu použít šablony
  • jak vytvářet odkazy

Instalace:

composer require nette/mail

Vytvoření & odeslání e-mailu

Příklad vytvoření e-mailu třídou Nette\Mail\Message:

use Nette\Mail\Message;

$mail = new Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Potvrzení objednávky')
	->setBody("Dobrý den,\nvaše objednávka byla přijata.");

Všechny zadávané parametry musí být v UTF-8.

A odeslání:

use Nette\Mail\SendmailMailer;

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

V presenterech a službách nevytvářime mailer ručně, ale pomocí DI si necháme předat Nette\Mail\IMailer.

Paráda, to snad ani nepotřebuje hlouběji rozebírat. Tak jen dodáme, že kromě uvedení příjemce metodou addTo() lze uvést i příjemce kopie addCc(), nebo příjemce skryté kopie addBcc(). Ve všech těchto metodách včetně setFrom() můžeme adresáta zapsat třemi způsoby:

$mail->setFrom('franta@example.com');
$mail->setFrom('franta@example.com', 'Franta');
$mail->setFrom('Franta <franta@example.com>');

HTML obsah se předává metodou setHtmlBody():

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

Vložené obrázky (embedded)

Vložené obrázky lze do emailu vkládat metodou $mail->addEmbeddedFile('background.gif'), nicméně není to potřeba. Proč? Protože Nette Framework sám vyhledá a vloží všechny soubory odkazované v HTML kódu (pouze relativní cesty). Toto chování lze vypnout uvedením false jakožto druhého parametru metody setHtmlBody(), v tomto parametru je též možno předat absolutní cestu ke složce s obrázky.

Pokud HTML email nemá textovou alternativu, bude vygenerována automaticky. A pokud HTML email nemá nastavený subjekt, bude vzat z elementu <title>.

Pokud chcete nastavit returnPath a server vám ho pořád přepisuje, použijte $commandArgs.

$mailer->commandArgs = '-fMuj@email.cz';

Nikdy neposílejte e-mailem hesla ani jiné přístupové údaje.

Přílohy

Do e-mailu lze samozřejmě vkládat i přílohy. Slouží k tomu metoda addAttachment:

// vloží do e-mailu soubor example.zip
$mail->addAttachment('path/to/example.zip');

// vloží do e-mailu soubor example.txt s textem "Hello John!"
$mail->addAttachment('example.txt', 'Hello John!');

// vloží do e-mailu soubor example.zip pojmenovaný info.zip
$mail->addAttachment('info.zip', file_get_contents('path/to/example.zip'));

Může být odesílání e-mailů ještě jednodušší?

Šablony

Skutečná síla se projeví při zkombinování se šablonovacím systémem Latte:

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

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

Soubor email.latte:

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Potvrzení objednávky</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Dobrý den,</p>

	<p>Vaše objednávka číslo {$orderId} byla přijata.</p>
</body>
</html>

Použití v Nette aplikaci

Šablonovací systém Latte ve svém základu nezná makro {link} ani atribut n:href (a některé další, například filtr translate). Ty doplňuje až třída TemplateFactory z balíčku nette/application ve spojení s presenterem. Abychom mohli vytvářet odkazy v šabloně emailu, necháme si šablonu vytvořit právě pomocí zmíněné TemplateFactory. A presenter nahradíme objektem LinkGenerator, který umí vytvářet odkazy. Oba objekty si předáme přes konstruktor a vytvoření šablony vidíte v metodě createTemplate():

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;
	}
}

V šabloně pak odkaz vytvoříme tak, jak jsme zvyklí. Všechny odkazy vytvořene přes LinkGenerator budou absolutní.

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


DKIM
====

DKIM (DomainKeys Identified Mail) je technologie pro zvýšení důvěryhodnosti emailů, která také napomáhá odhalení podvržených zpráv. Odeslaná zpráva je SMTP serverem podepsána privátním klíčem domény odesílatele a tento podpis je uložen v hlavičce emailu.
Server příjemce porovná tento podpis s veřejným klíčem uloženým v DNS záznamech domény. Tím, že podpis odpovídá, je prokázáno, že e-mail skutečně pochází z odesílatelovy domény a že během přenosu zprávy nedošlo k její úpravě.

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

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

Mailery

Mailer je třída zajišťující odesílání e-mailů. Můžeme si také vytvořit vlastní mailer, jedná se o objekt implementující rozhraní Nette\Mail\IMailer.

SendmailMailer

Výchozí mailer je SendmailMailer, který používá PHP funkci mail.

SmtpMailer

K odeslání pošty přes SMTP server slouží SmtpMailer.

$mailer = new Nette\Mail\SmtpMailer([
	'host' => 'smtp.gmail.com', //  pokud není nastaven, použijí se hodnoty z php.ini
	'username' => 'franta@gmail.com',
	'password' => '*****',
	'secure' => 'ssl',
]);
$mailer->send($mail);

Kromě nastavení výše, SmtpMailer nabízí další klíče pro přizpůsobení:

  • port – Pokud není nastaven, určí se podle klíče secure: 465 pro hodnotu ssl, jinak 25.
  • context – Umožňuje nastavit spojení se SMTP skrz SSL context options. Obsahuje pole jednotlivých nastavení.
  • timeout – Timeout pro SMTP spojení
  • persistent – Použít persistent spojení
  • clientHost – Nastavení hlavičky Host klienta

Většinu těchto hodnot lze nastavit také přímo v konfiguraci frameworku

FallbackMailer

Emaily přímo neodesílá, ale odesílání zprostředkovává přes sadu mailerů. V případě, že jeden mailer selže, zopakuje pokus u dalšího. Pokud selže i poslední, začíná znovu od prvního.

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

Jako další parametry v konstruktoru můžeme uvést počet opakování a čekací dobu (v milisekundách).

Související články na blogu