Nette Documentation Preview

syntax
Invio di e-mail
***************

<div class=perex>

State per inviare e-mail, ad esempio newsletter o conferme d'ordine? Nette Framework fornisce gli strumenti necessari con un'API molto piacevole. Vedremo:

- come creare un'e-mail, incluse le allegate
- come inviarla
- come collegare e-mail e template

</div>


Installazione
=============

Scaricate e installate la libreria utilizzando lo strumento [Composer|best-practices:composer]:

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


Creazione di un'e-mail
======================

L'e-mail è un oggetto della classe [api:Nette\Mail\Message]. Lo creiamo ad esempio così:

```php
$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Conferma ordine')
	->setBody("Buongiorno,\nil suo ordine è stato ricevuto.");
```

Tutti i parametri inseriti devono essere in UTF-8.

Oltre a specificare il destinatario con il metodo `addTo()`, è possibile specificare anche il destinatario della copia `addCc()`, o il destinatario della copia nascosta `addBcc()`. In tutti questi metodi, incluso `setFrom()`, possiamo scrivere l'indirizzo in tre modi:

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

Il corpo dell'e-mail scritto in HTML viene passato con il metodo `setHtmlBody()`:

```php
$mail->setHtmlBody('<p>Buongiorno,</p><p>il suo ordine è stato ricevuto.</p>');
```

Non è necessario creare l'alternativa testuale, Nette la genererà automaticamente per voi. E se l'e-mail non ha un oggetto impostato, cercherà di prenderlo dall'elemento `<title>`.

È anche straordinariamente facile inserire immagini nel corpo HTML. Basta passare come secondo parametro il percorso dove si trovano fisicamente le immagini, e Nette le includerà automaticamente nell'e-mail:

```php
// aggiunge automaticamente /path/to/images/background.gif all'e-mail
$mail->setHtmlBody(
	'<b>Hello</b> <img src="background.gif">',
	'/path/to/images',
);
```

L'algoritmo che inserisce le immagini cerca questi pattern: `<img src=...>`, `<body background=...>`, `url(...)` all'interno dell'attributo HTML `style` e la sintassi speciale `[[...]]`.

L'invio di e-mail può essere ancora più semplice?

.[tip]
L'e-mail è come una cartolina. Non inviate mai password o altri dati di accesso via e-mail.


Allegati
--------

Naturalmente, è possibile inserire allegati nell'e-mail. A questo serve il metodo `addAttachment(string $file, ?string $content = null, ?string $contentType = null)`.

```php
// inserisce il file /path/to/example.zip nell'e-mail con il nome example.zip
$mail->addAttachment('/path/to/example.zip');

// inserisce il file /path/to/example.zip nell'e-mail chiamato info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// inserisce il file example.txt nell'e-mail con il contenuto "Hello John!"
$mail->addAttachment('example.txt', 'Hello John!');
```


Template
--------

Se inviate e-mail HTML, è naturale scriverle nel sistema di template [Latte|latte:]. Come fare?

```php
$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',
	);
```

File `email.latte`:

```latte
<html>
<head>
	<meta charset="utf-8">
	<title>Conferma ordine</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Buongiorno,</p>

	<p>Il suo ordine numero {$orderId} è stato ricevuto.</p>
</body>
</html>
```

Nette inserirà automaticamente tutte le immagini, imposterà l'oggetto secondo l'elemento `<title>` e genererà l'alternativa testuale all'HTML.


Utilizzo in Nette Application
-----------------------------

Se usate le e-mail insieme a Nette Application, cioè con i presenter, potreste voler creare link nei template usando l'attributo `n:href` o il tag `{link}`. Latte non li conosce di base, ma è molto facile aggiungerli. L'oggetto `Nette\Application\LinkGenerator` può creare link, e potete ottenerlo facendovelo passare tramite [dependency injection |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;
	}
}
```

Nel template, creiamo quindi i link come siamo abituati. Tutti i link creati tramite LinkGenerator saranno assoluti.

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


Invio dell'e-mail
=================

Mailer è la classe che si occupa dell'invio delle e-mail. Implementa l'interfaccia [api:Nette\Mail\Mailer] e sono disponibili diversi mailer predefiniti che presenteremo.

Il framework aggiunge automaticamente al container DI un servizio di tipo `Nette\Mail\Mailer` costruito sulla base della [#configurazione], a cui potete accedere facendovelo passare tramite [dependency injection |dependency-injection:passing-dependencies].


SendmailMailer
--------------

Il mailer predefinito è SendmailMailer, che utilizza la funzione PHP [php:mail]. Esempio di utilizzo:

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

Se volete impostare `returnPath` e il server continua a sovrascriverlo, usate `$mailer->commandArgs = '-fMio@email.it'`.


SmtpMailer
----------

Per inviare posta tramite un server SMTP si usa `SmtpMailer`.

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

Al costruttore possono essere passati questi altri parametri:

* `port` - se non impostato, viene utilizzato il predefinito 25 o 465 per `ssl`
* `timeout` - timeout per la connessione SMTP
* `persistent` - usare una connessione persistente
* `clientHost` - impostazione dell'header Host del client
* `streamOptions` - consente di impostare le "SSL context options":https://www.php.net/manual/en/context.ssl.php per la connessione


FallbackMailer
--------------

Non invia direttamente le e-mail, ma ne gestisce l'invio tramite un set di mailer. Nel caso in cui un mailer fallisca, ripete il tentativo con il successivo. Se fallisce anche l'ultimo, ricomincia dal primo.

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

Come altri parametri nel costruttore possiamo specificare il numero di ripetizioni e il tempo di attesa in millisecondi.


DKIM
====

DKIM (DomainKeys Identified Mail) è una tecnologia per aumentare l'affidabilità delle e-mail, che aiuta anche a rilevare messaggi contraffatti. Il messaggio inviato è firmato con la chiave privata del dominio del mittente e questa firma è memorizzata nell'intestazione dell'e-mail. Il server del destinatario confronta questa firma con la chiave pubblica memorizzata nei record DNS del dominio. Se la firma corrisponde, viene dimostrato che l'e-mail proviene effettivamente dal dominio del mittente e che durante la trasmissione del messaggio non è stata apportata alcuna modifica.

Potete impostare la firma delle e-mail per il mailer direttamente nella [configurazione|#Configurazione]. Se non usate la dependency injection, si usa in questo modo:

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

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


Configurazione
==============

Panoramica delle opzioni di configurazione per Nette Mail. Se non utilizzate l'intero framework, ma solo questa libreria, leggete [come caricare la configurazione|bootstrap:].

Per l'invio di e-mail si utilizza di default il mailer `Nette\Mail\SendmailMailer`, che non viene ulteriormente configurato. Possiamo però passare a `Nette\Mail\SmtpMailer`:

```neon
mail:
	# usa SmtpMailer
	smtp: true       # (bool) predefinito è false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) predefinito è null (ha alias 'secure')
	clientHost: ...  # (string) predefinito è $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) predefinito è false

	# contesto per la connessione al server SMTP, predefinito è stream_context_get_default()
	context:
		ssl:         # panoramica delle opzioni su https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # panoramica delle opzioni su https://www.php.net/manual/en/context.http.php
			header: ...
			...
```

Con l'opzione `context › ssl › verify_peer: false` è possibile disattivare la verifica dei certificati SSL. **Sconsigliamo vivamente** di farlo, perché l'applicazione diventerebbe vulnerabile. Invece, "aggiungete i certificati allo store":https://www.php.net/manual/en/openssl.configuration.php.

Per aumentare l'affidabilità, possiamo firmare le e-mail utilizzando la [tecnologia DKIM |https://blog.nette.org/cs/podepisujte-emaily-pomoci-dkim]:

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


Servizi DI
==========

Questi servizi vengono aggiunti al container DI:

| Nome            | Tipo                      | Descrizione
|------------------------------------------------------
| `mail.mailer`	  | [api:Nette\Mail\Mailer]   | [classe che invia le e-mail |#Invio dell'e-mail]
| `mail.signer`	  | [api:Nette\Mail\Signer]   | [Firma DKIM |#DKIM]


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

Invio di e-mail

State per inviare e-mail, ad esempio newsletter o conferme d'ordine? Nette Framework fornisce gli strumenti necessari con un'API molto piacevole. Vedremo:

  • come creare un'e-mail, incluse le allegate
  • come inviarla
  • come collegare e-mail e template

Installazione

Scaricate e installate la libreria utilizzando lo strumento Composer:

composer require nette/mail

Creazione di un'e-mail

L'e-mail è un oggetto della classe Nette\Mail\Message. Lo creiamo ad esempio così:

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Conferma ordine')
	->setBody("Buongiorno,\nil suo ordine è stato ricevuto.");

Tutti i parametri inseriti devono essere in UTF-8.

Oltre a specificare il destinatario con il metodo addTo(), è possibile specificare anche il destinatario della copia addCc(), o il destinatario della copia nascosta addBcc(). In tutti questi metodi, incluso setFrom(), possiamo scrivere l'indirizzo in tre modi:

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

Il corpo dell'e-mail scritto in HTML viene passato con il metodo setHtmlBody():

$mail->setHtmlBody('<p>Buongiorno,</p><p>il suo ordine è stato ricevuto.</p>');

Non è necessario creare l'alternativa testuale, Nette la genererà automaticamente per voi. E se l'e-mail non ha un oggetto impostato, cercherà di prenderlo dall'elemento <title>.

È anche straordinariamente facile inserire immagini nel corpo HTML. Basta passare come secondo parametro il percorso dove si trovano fisicamente le immagini, e Nette le includerà automaticamente nell'e-mail:

// aggiunge automaticamente /path/to/images/background.gif all'e-mail
$mail->setHtmlBody(
	'<b>Hello</b> <img src="background.gif">',
	'/path/to/images',
);

L'algoritmo che inserisce le immagini cerca questi pattern: <img src=...>, <body background=...>, url(...) all'interno dell'attributo HTML style e la sintassi speciale [[...]].

L'invio di e-mail può essere ancora più semplice?

L'e-mail è come una cartolina. Non inviate mai password o altri dati di accesso via e-mail.

Allegati

Naturalmente, è possibile inserire allegati nell'e-mail. A questo serve il metodo addAttachment(string $file, ?string $content = null, ?string $contentType = null).

// inserisce il file /path/to/example.zip nell'e-mail con il nome example.zip
$mail->addAttachment('/path/to/example.zip');

// inserisce il file /path/to/example.zip nell'e-mail chiamato info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// inserisce il file example.txt nell'e-mail con il contenuto "Hello John!"
$mail->addAttachment('example.txt', 'Hello John!');

Template

Se inviate e-mail HTML, è naturale scriverle nel sistema di template Latte. Come fare?

$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',
	);

File email.latte:

<html>
<head>
	<meta charset="utf-8">
	<title>Conferma ordine</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Buongiorno,</p>

	<p>Il suo ordine numero {$orderId} è stato ricevuto.</p>
</body>
</html>

Nette inserirà automaticamente tutte le immagini, imposterà l'oggetto secondo l'elemento <title> e genererà l'alternativa testuale all'HTML.

Utilizzo in Nette Application

Se usate le e-mail insieme a Nette Application, cioè con i presenter, potreste voler creare link nei template usando l'attributo n:href o il tag {link}. Latte non li conosce di base, ma è molto facile aggiungerli. L'oggetto Nette\Application\LinkGenerator può creare link, e potete ottenerlo facendovelo passare tramite 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;
	}
}

Nel template, creiamo quindi i link come siamo abituati. Tutti i link creati tramite LinkGenerator saranno assoluti.

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

Invio dell'e-mail

Mailer è la classe che si occupa dell'invio delle e-mail. Implementa l'interfaccia Nette\Mail\Mailer e sono disponibili diversi mailer predefiniti che presenteremo.

Il framework aggiunge automaticamente al container DI un servizio di tipo Nette\Mail\Mailer costruito sulla base della configurazione, a cui potete accedere facendovelo passare tramite dependency injection.

SendmailMailer

Il mailer predefinito è SendmailMailer, che utilizza la funzione PHP mail. Esempio di utilizzo:

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

Se volete impostare returnPath e il server continua a sovrascriverlo, usate $mailer->commandArgs = '-fMio@email.it'.

SmtpMailer

Per inviare posta tramite un server SMTP si usa SmtpMailer.

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

Al costruttore possono essere passati questi altri parametri:

  • port – se non impostato, viene utilizzato il predefinito 25 o 465 per ssl
  • timeout – timeout per la connessione SMTP
  • persistent – usare una connessione persistente
  • clientHost – impostazione dell'header Host del client
  • streamOptions – consente di impostare le SSL context options per la connessione

FallbackMailer

Non invia direttamente le e-mail, ma ne gestisce l'invio tramite un set di mailer. Nel caso in cui un mailer fallisca, ripete il tentativo con il successivo. Se fallisce anche l'ultimo, ricomincia dal primo.

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

Come altri parametri nel costruttore possiamo specificare il numero di ripetizioni e il tempo di attesa in millisecondi.

DKIM

DKIM (DomainKeys Identified Mail) è una tecnologia per aumentare l'affidabilità delle e-mail, che aiuta anche a rilevare messaggi contraffatti. Il messaggio inviato è firmato con la chiave privata del dominio del mittente e questa firma è memorizzata nell'intestazione dell'e-mail. Il server del destinatario confronta questa firma con la chiave pubblica memorizzata nei record DNS del dominio. Se la firma corrisponde, viene dimostrato che l'e-mail proviene effettivamente dal dominio del mittente e che durante la trasmissione del messaggio non è stata apportata alcuna modifica.

Potete impostare la firma delle e-mail per il mailer direttamente nella configurazione. Se non usate la dependency injection, si usa in questo modo:

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

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

Configurazione

Panoramica delle opzioni di configurazione per Nette Mail. Se non utilizzate l'intero framework, ma solo questa libreria, leggete come caricare la configurazione.

Per l'invio di e-mail si utilizza di default il mailer Nette\Mail\SendmailMailer, che non viene ulteriormente configurato. Possiamo però passare a Nette\Mail\SmtpMailer:

mail:
	# usa SmtpMailer
	smtp: true       # (bool) predefinito è false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) predefinito è null (ha alias 'secure')
	clientHost: ...  # (string) predefinito è $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) predefinito è false

	# contesto per la connessione al server SMTP, predefinito è stream_context_get_default()
	context:
		ssl:         # panoramica delle opzioni su https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # panoramica delle opzioni su https://www.php.net/manual/en/context.http.php
			header: ...
			...

Con l'opzione context › ssl › verify_peer: false è possibile disattivare la verifica dei certificati SSL. Sconsigliamo vivamente di farlo, perché l'applicazione diventerebbe vulnerabile. Invece, aggiungete i certificati allo store.

Per aumentare l'affidabilità, possiamo firmare le e-mail utilizzando la tecnologia DKIM:

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

Servizi DI

Questi servizi vengono aggiunti al container DI:

Nome Tipo Descrizione
mail.mailer Nette\Mail\Mailer classe che invia le e-mail
mail.signer Nette\Mail\Signer Firma DKIM