Nette Documentation Preview

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

<div class=perex>

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

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

</div>


Настройка .[#toc-installation]
==============================

Изтеглете и инсталирайте пакета с помощта на [Composer |best-practices:composer]:

```shell
composer require nette/mail
```


Създаване на имейли .[#toc-creating-emails]
===========================================

Електронната поща е обект на [api:Nette\Mail\Message]:

```php
$mail = new Nette\Mail\Message;
$mail->setFrom('John <john@example.com>')
	->addTo('peter@example.com')
	->addTo('jack@example.com')
	->setSubject('Подтверждение заказа')
	->setBody("Здравствуйте. Ваш заказ принят.");
```

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

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

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

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

```php
$mail->setHtmlBody('<p>Hello,</p><p>Ваш заказ принят.</p>');
```

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

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

```php
// автоматично добавя /path/to/images/background.gif към имейла
$mail->setHtmlBody(
	'<b>Hello</b> <img src="background.gif">',
	'/path/to/images',
);
```

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

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

Имейлите са като пощенски картички. Никога не изпращайте пароли или други идентификационни данни по имейл. .[tip]


Прикачени файлове .[#toc-attachments]
-------------------------------------

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

```php
//вмъкнете файла /path/to/example.zip в имейла като example.zip
$mail->addAttachment('/path/to/example.zip');

//вмъкнете файла /path/to/example.zip в имейла като info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

//вмъкнете файла example.txt с текста "Здравей, Джон!
$mail->addAttachment('example.txt', 'Hello John!');
```


Шаблони .[#toc-templates]
-------------------------

Ако изпращате имейли в HTML формат, е чудесна идея да ги напишете в системата за шаблони [Latte |latte:]. Как да го направим?

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

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

Файл `email.latte`:

```latte
<html>
<head>
	<meta charset="utf-8">
	<title>Подтверждение заказа</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Здравствуйте!</p>

	<p>Ваш заказ под номером {$orderId} был принят.</p>
</body>
</html>
```

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


Използване в приложението Nette .[#toc-using-in-nette-application]
------------------------------------------------------------------

Ако използвате електронна поща заедно с Nette Application, т.е. презентатори, може да искате да създадете връзки в шаблоните, като използвате атрибута `n:href` или тага `{link}`. Latte не ги познава по принцип, но те са много лесни за добавяне. Създаването на връзки може да се обработва от обекта `Nette\Application\LinkGenerator`, който получавате чрез предаването му с помощта на [вграждане на зависимости |dependency-injection:passing-dependencies].

```php
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, са абсолютни:

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


Изпращане на имейли .[#toc-sending-emails]
==========================================

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

Рамката автоматично добавя услугата `Nette\Mail\Mailer`, [базирана на конфигурация, |#Configuring] към контейнера DI, който получавате, като го предавате чрез [инжектиране на зависимости |dependency-injection:passing-dependencies].


SendmailMailer .[#toc-sendmailmailer]
-------------------------------------

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

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

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


SmtpMailer .[#toc-smtpmailer]
-----------------------------

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

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

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

* `port` - ако не е посочена, ще се използва стойността по подразбиране от 25 или 465 за `ssl`.
* `timeout` - таймаут за SMTP връзка
* `persistent` - използвайте постоянна връзка
* `clientHost` - възлагане на клиента
* `streamOptions` - позволява ви да зададете "SSL контекстни опции" за:https://www.php.net/manual/ru/context.ssl.php връзката


FallbackMailer .[#toc-fallbackmailer]
-------------------------------------

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

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

Другите параметри в конструктора включват броя на повторенията и времето за изчакване в милисекунди.


DKIM .[#toc-dkim]
=================

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

Можете да [конфигурирате |#Configuring] пощенския оператор за подписване на имейли в [конфигурацията |#Configuring]. Ако не използвате налагане на зависимости, тя се задава по следния начин:

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

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


Конфигурация .[#toc-configuring]
================================

Преглед на конфигурационните настройки за Nette Mail. Ако не използвате цялата рамка, а само тази библиотека, прочетете [Как да изтеглите конфигурационния файл |bootstrap:].

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

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

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) по подразбиране е null
	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
			заглавие: ...
			...
```

Можете да деактивирате удостоверяването на SSL сертификат, като използвате опцията `context › ssl › verify_peer: false`. Силно се препоръчва **да не правите това**, тъй като това ще направи приложението уязвимо. Вместо това "добавете сертификати в хранилището за доверие":https://www.php.net/manual/en/openssl.configuration.php.

За да повишим доверието, можем да подписваме имейли с помощта на [технологията DKIM |https://blog.nette.org/bg/podpisvane-na-imejli-s-dkim]:

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


Услуги на DI .[#toc-di-services]
================================

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

| Име | Тип | Описание
|-----------------------------------------------------
| `mail.mailer`| [api:Nette\Mail\Mailer] | [клас за изпращане на електронна поща |#Sending Emails]
| `mail.signer`| [api:Nette\Mail\Signer] | [DKIM подписване |#DKIM]


{{leftbar: nette:@menu-topics}}

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

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

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

Настройка

Изтеглете и инсталирайте пакета с помощта на Composer:

composer require nette/mail

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

Електронната поща е обект на Nette\Mail\Message:

$mail = new Nette\Mail\Message;
$mail->setFrom('John <john@example.com>')
	->addTo('peter@example.com')
	->addTo('jack@example.com')
	->setSubject('Подтверждение заказа')
	->setBody("Здравствуйте. Ваш заказ принят.");

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

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

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

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

$mail->setHtmlBody('<p>Hello,</p><p>Ваш заказ принят.</p>');

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

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

// автоматично добавя /path/to/images/background.gif към имейла
$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).

//вмъкнете файла /path/to/example.zip в имейла като example.zip
$mail->addAttachment('/path/to/example.zip');

//вмъкнете файла /path/to/example.zip в имейла като info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

//вмъкнете файла example.txt с текста "Здравей, Джон!
$mail->addAttachment('example.txt', 'Hello John!');

Шаблони

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

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

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

Файл email.latte:

<html>
<head>
	<meta charset="utf-8">
	<title>Подтверждение заказа</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Здравствуйте!</p>

	<p>Ваш заказ под номером {$orderId} был принят.</p>
</body>
</html>

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

Използване в приложението Nette

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

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">Link</a>

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

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

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

SendmailMailer

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

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

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

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 – таймаут за SMTP връзка
  • persistent – използвайте постоянна връзка
  • clientHost – възлагане на клиента
  • streamOptions – позволява ви да зададете „SSL контекстни опции“ за:https://www.php.net/…text.ssl.php връзката

FallbackMailer

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

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

Другите параметри в конструктора включват броя на повторенията и времето за изчакване в милисекунди.

DKIM

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

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

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

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

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

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

По подразбиране за изпращане на имейли се използва пощенският оператор 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
	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
			заглавие: ...
			...

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

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

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

Услуги на DI

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

Име Тип Описание
mail.mailer Nette\Mail\Mailer клас за изпращане на електронна поща
mail.signer Nette\Mail\Signer DKIM подписване