Nette Documentation Preview

syntax
Надсилання електронних листів
*****************************

<div class=perex>

Чи збираєтеся ви надсилати електронні листи, наприклад, інформаційні бюлетені або підтвердження замовлень? Фреймворк Nette надає необхідні інструменти з дуже зручним API. Ми покажемо:

- як створити електронний лист, включно з вкладеннями
- як відправити
- як об'єднати електронні листи та шаблони

</div>


Встановлення .[#toc-installation]
=================================

Завантажте та встановіть пакет за допомогою [Composer |best-practices:composer]:

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


Створення електронних листів .[#toc-creating-emails]
====================================================

Email - це об'єкт [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>Привіт</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 із текстом "Hello John!"
$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` на основі [configuration |#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-записах домену. Звіряючи підпис, можна довести, що електронний лист справді надійшов із домену відправника і що повідомлення не було змінено під час його передавання.

Ви можете налаштувати mailer для підпису електронної пошти в [конфігурації |#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
			header: ...
			...
```

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

Щоб підвищити довіру, ми можемо підписувати електронні листи за допомогою [технології DKIM |https://blog.nette.org/uk/pidpisujte-elektronni-listi-za-dopomogoyu-dkim]:

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


Послуги з проведення розслідувань .[#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

Створення електронних листів

Email – це об'єкт 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>Привіт</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 із текстом "Hello John!"
$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 на основі configuration в контейнер 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 для з'єднання

FallbackMailer

Він не надсилає листи електронною поштою, а розсилає їх через набір розсилок. Якщо одна розсилка не вдалася, вона повторює спробу на наступній. Якщо остання з них не працює, то все починається заново з першої.

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

Інші параметри в конструкторі включають число повторів і час очікування в мілісекундах.

DKIM

DKIM (DomainKeys Identified Mail) – це технологія надійної електронної пошти, яка також допомагає виявити підроблені повідомлення. Відправлене повідомлення підписується закритим ключем домену відправника, і цей підпис зберігається в заголовку електронної пошти. Сервер одержувача порівнює цей підпис із відкритим ключем, що зберігається в DNS-записах домену. Звіряючи підпис, можна довести, що електронний лист справді надійшов із домену відправника і що повідомлення не було змінено під час його передавання.

Ви можете налаштувати mailer для підпису електронної пошти в конфігурації. Якщо ви не використовуєте впровадження залежностей, він задається таким чином:

$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
			header: ...
			...

Ви можете вимкнути перевірку автентичності SSL-сертифіката за допомогою опції context › ssl › verify_peer: false. Настійно рекомендується не робити цього, оскільки це зробить додаток вразливим. Натомість, додайте сертифікати до сховища довіри.

Щоб підвищити довіру, ми можемо підписувати електронні листи за допомогою технології DKIM:

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

Послуги з проведення розслідувань

Ці сервіси додаються до контейнера DI:

Назва Тип Опис
mail.mailer Nette\Mail\Mailer клас відправлення електронноїпошти
mail.signer Nette\Mail\Signer підписання DKIM