Поща

Изпращане на
Имейли

Изпращане на имейли

Предстои ви да изпращате имейли, например бюлетини или потвърждения на поръчки? Nette Framework предоставя необходимите инструменти с много приятен API. Ще ви покажем:

  • как да създадете имейл, включително прикачени файлове
  • как да го изпратите
  • как да свържете имейли и шаблони

Инсталация

Можете да изтеглите и инсталирате библиотеката с помощта на инструмента Composer:

composer require nette/mail

Създаване на имейл

Имейлът е обект от класа Nette\Mail\Message. Нека го създадем по следния начин:

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Potvrzení objednávky') // Confirmation of order
	->setBody("Dobrý den,\nvaše objednávka byla přijata."); // Hello,\nyour order has been accepted.

Всички въведени параметри трябва да са в UTF-8.

Освен посочването на получател с метода addTo(), можете да посочите и получател на копие addCc() или получател на скрито копие addBcc(). Във всички тези методи, включително setFrom(), можем да запишем адресата по три начина:

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

Тялото на имейла, написано в HTML, се предава чрез метода setHtmlBody():

$mail->setHtmlBody('<p>Dobrý den,</p><p>vaše objednávka byla přijata.</p>'); // <p>Hello,</p><p>your order has been accepted.</p>

Не е необходимо да създавате текстова алтернатива, Nette ще я генерира автоматично за вас. И ако имейлът няма зададена тема, той ще се опита да я вземе от елемента <title>.

Също така е изключително лесно да вмъквате изображения в тялото на HTML. Просто предайте пътя, където изображенията се намират физически, като втори параметър и Nette автоматично ще ги включи в имейла:

// automaticky přidá /path/to/images/background.gif do e-mailu
$mail->setHtmlBody(
	'<b>Hello</b> <img src="background.gif">',
	'/path/to/images',
);

Алгоритъмът, който вмъква изображения, търси следните шаблони: <img src=...>, <body background=...>, url(...) вътре в HTML атрибута style и специалния синтаксис [[...]].

Може ли изпращането на имейли да бъде още по-лесно?

Имейлът е като пощенска картичка. Никога не изпращайте пароли или други данни за достъп по имейл.

Прикачени файлове

Разбира се, към имейла могат да се добавят прикачени файлове. За тази цел се използва методът addAttachment(string $file, ?string $content = null, ?string $contentType = null).

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

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

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

Шаблони

Ако изпращате HTML имейли, е съвсем естествено да ги пишете в системата за шаблони Latte. Как да го направите?

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

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->setHtmlBody(
		$latte->renderToString('/path/to/email.latte', $params),
		'/path/to/images',
	);

Файл email.latte:

<html>
<head>
	<meta charset="utf-8">
	<title>Potvrzení objednávky</title>  {* Confirmation of order *}
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Dobrý den,</p> {* Hello, *}

	<p>Vaše objednávka číslo {$orderId} byla přijata.</p> {* Your order number {$orderId} has been accepted. *}
</body>
</html>

Nette автоматично ще вмъкне всички изображения, ще зададе темата според елемента <title> и ще генерира текстова алтернатива на HTML.

Използване в Nette Application

Ако използвате имейли заедно с Nette Application, т.е. с презентери, може да искате да създавате връзки в шаблоните с помощта на атрибута n:href или тага {link}. Latte не ги познава по подразбиране, но е много лесно да ги добавите. Обектът Nette\Application\LinkGenerator може да създава връзки, до които можете да получите достъп, като го предадете чрез dependency injection:

use Nette;

class MailSender
{
	public function __construct(
		private Nette\Application\LinkGenerator $linkGenerator,
		private Nette\Bridges\ApplicationLatte\TemplateFactory $templateFactory,
	) {
	}

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

	public function createEmail(): Nette\Mail\Message
	{
		$template = $this->createTemplate();
		$html = $template->renderToString('/path/to/email.latte', $params);

		$mail = new Nette\Mail\Message;
		$mail->setHtmlBody($html);
		// ...
		return $mail;
	}
}

След това създаваме връзки в шаблона, както сме свикнали. Всички връзки, създадени чрез LinkGenerator, ще бъдат абсолютни.

<a n:href="Presenter:action">Odkaz</a> {* Link *}

Изпращане на имейл

Mailer е клас, който осигурява изпращането на имейли. Той имплементира интерфейса Nette\Mail\Mailer и има няколко предварително подготвени мейлъра, които ще представим.

Framework автоматично добавя сървис от тип Nette\Mail\Mailer към DI контейнера, изграден въз основа на #конфигурацията, до който можете да получите достъп, като го предадете чрез dependency injection.

SendmailMailer

Мейлърът по подразбиране е SendmailMailer, който използва PHP функцията mail. Пример за използване:

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

Ако искате да зададете returnPath и сървърът ви продължава да го презаписва, използвайте $mailer->commandArgs = '-fMuj@email.cz'.

SmtpMailer

За изпращане на поща чрез SMTP сървър се използва SmtpMailer.

$mailer = new Nette\Mail\SmtpMailer(
	host: 'smtp.gmail.com',
	username: 'franta@gmail.com',
	password: '*****',
	encryption: 'ssl',
);
$mailer->send($mail);

На конструктора могат да бъдат предадени следните допълнителни параметри:

  • port – ако не е зададен, се използва порт по подразбиране 25 или 465 за ssl
  • timeout – timeout за SMTP връзка
  • persistent – използване на постоянна връзка
  • clientHost – настройка на хедъра Host на клиента
  • streamOptions – позволява настройка на SSL context options за връзката

FallbackMailer

Той не изпраща имейли директно, а посредничи при изпращането чрез набор от мейлъри. В случай, че един мейлър се провали, той повтаря опита със следващия. Ако и последният се провали, започва отново от първия.

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

Като допълнителни параметри в конструктора можем да посочим броя на повторенията и времето за изчакване в милисекунди.

DKIM

DKIM (DomainKeys Identified Mail) е технология за повишаване на достоверността на имейлите, която също помага за разкриването на фалшифицирани съобщения. Изпратеното съобщение се подписва с частния ключ на домейна на изпращача и този подпис се съхранява в хедъра на имейла. Сървърът на получателя сравнява този подпис с публичния ключ, съхранен в DNS записите на домейна. Съответствието на подписа доказва, че имейлът действително произхожда от домейна на изпращача и че не е имало промяна в съобщението по време на преноса му.

Можете да настроите подписването на имейли за мейлъра директно в конфигурацията. Ако не използвате dependency injection, се използва по следния начин:

$signer = new Nette\Mail\DkimSigner(
	domain: 'nette.org',
	selector: 'dkim',
	privateKey: file_get_contents('../dkim/dkim.key'),
	passPhrase: '****',
);

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

Конфигурация

Преглед на конфигурационните опции за Nette Mail. Ако не използвате целия framework, а само тази библиотека, прочетете как да заредите конфигурацията.

За изпращане на имейли стандартно се използва мейлърът Nette\Mail\SendmailMailer, който не се конфигурира допълнително. Можем обаче да го превключим на Nette\Mail\SmtpMailer:

mail:
	# използва SmtpMailer
	smtp: true       # (bool) по подразбиране е false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) по подразбиране е null (има псевдоним 'secure')
	clientHost: ...  # (string) по подразбиране е $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) по подразбиране е false

	# контекст за връзка със SMTP сървъра, по подразбиране е stream_context_get_default()
	context:
		ssl:         # преглед на опциите на https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # преглед на опциите на https://www.php.net/manual/en/context.http.php
			header: ...
			...

С помощта на опцията context › ssl › verify_peer: false може да се изключи проверката на SSL сертификати. Силно не препоръчваме да правите това, защото приложението ще стане уязвимо. Вместо това добавете сертификати в хранилището.

За повишаване на достоверността можем да подписваме имейлите с помощта на технологията DKIM:

mail:
	dkim:
		domain: myweb.com
		selector: lovenette
		privateKey: %appDir%/cert/dkim.priv
		passPhrase: ...

DI Сървиси

Тези сървиси се добавят към DI контейнера:

Име Тип Описание
mail.mailer Nette\Mail\Mailer [клас, изпращащ имейли #Изпращане на имейл |#Odeslání e-mailu]
mail.signer Nette\Mail\Signer [DKIM подписване #DKIM |#DKIM]
версия: 4.0