Nette Documentation Preview

syntax
Enviando e-mails
****************

<div class=perex>

Você vai enviar e-mails, como newsletters ou confirmações de pedidos? O Nette Framework fornece as ferramentas necessárias com uma API muito agradável. Vamos mostrar:

- como criar um e-mail, incluindo anexos
- como enviá-lo
- como conectar e-mails e templates

</div>


Instalação
==========

Baixe e instale a biblioteca usando o [Composer |best-practices:composer]:

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


Criando um e-mail
=================

Um e-mail é um objeto da classe [api:Nette\Mail\Message]. Vamos criá-lo assim:

```php
$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Confirmação do pedido')
	->setBody("Olá,\nseu pedido foi recebido.");
```

Todos os parâmetros inseridos devem estar em UTF-8.

Além de especificar o destinatário com o método `addTo()`, também é possível especificar o destinatário da cópia `addCc()`, ou o destinatário da cópia oculta `addBcc()`. Em todos esses métodos, incluindo `setFrom()`, podemos escrever o destinatário de três maneiras:

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

O corpo do e-mail escrito em HTML é passado pelo método `setHtmlBody()`:

```php
$mail->setHtmlBody('<p>Olá,</p><p>seu pedido foi recebido.</p>');
```

Você não precisa criar a alternativa de texto, o Nette a gerará automaticamente para você. E se o e-mail não tiver um assunto definido, ele tentará pegá-lo do elemento `<title>`.

Também é extraordinariamente fácil inserir imagens no corpo HTML. Basta passar o caminho onde as imagens estão fisicamente localizadas como segundo parâmetro, e o Nette as incluirá automaticamente no e-mail:

```php
// adiciona automaticamente /path/to/images/background.gif ao e-mail
$mail->setHtmlBody(
	'<b>Olá</b> <img src="background.gif">',
	'/path/to/images',
);
```

O algoritmo que insere imagens procura por estes padrões: `<img src=...>`, `<body background=...>`, `url(...)` dentro do atributo HTML `style` e a sintaxe especial `[[...]]`.

Enviar e-mails pode ser ainda mais fácil?

.[tip]
Um e-mail é como um cartão postal. Nunca envie senhas ou outras credenciais por e-mail.


Anexos
------

Claro, anexos podem ser inseridos no e-mail. O método `addAttachment(string $file, ?string $content = null, ?string $contentType = null)` é usado para isso.

```php
// insere o arquivo /path/to/example.zip no e-mail com o nome example.zip
$mail->addAttachment('/path/to/example.zip');

// insere o arquivo /path/to/example.zip no e-mail chamado info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// insere o arquivo example.txt no e-mail com o conteúdo "Olá John!"
$mail->addAttachment('example.txt', 'Olá John!');
```


Templates
---------

Se você envia e-mails HTML, é natural escrevê-los no sistema de templates [Latte |latte:]. Como fazer isso?

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

Arquivo `email.latte`:

```latte
<html>
<head>
	<meta charset="utf-8">
	<title>Confirmação do pedido</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Olá,</p>

	<p>Seu pedido número {$orderId} foi recebido.</p>
</body>
</html>
```

O Nette insere automaticamente todas as imagens, define o assunto de acordo com o elemento `<title>` e gera uma alternativa de texto para o HTML.


Uso no Nette Application
------------------------

Se você usa e-mails em conjunto com o Nette Application, ou seja, com presenters, pode querer criar links nos templates usando o atributo `n:href` ou a tag `{link}`. O Latte não os conhece por padrão, mas é muito fácil adicioná-los. O objeto `Nette\Application\LinkGenerator` pode criar links, e você pode acessá-lo pedindo para ser passado via [injeção de dependência |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;
	}
}
```

No template, criamos links da maneira que estamos acostumados. Todos os links criados através do LinkGenerator serão absolutos.

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


Enviando e-mail
===============

Mailer é uma classe que garante o envio de e-mails. Implementa a interface [api:Nette\Mail\Mailer] e existem vários mailers pré-preparados disponíveis, que apresentaremos.

O framework adiciona automaticamente um serviço do tipo `Nette\Mail\Mailer` ao contêiner DI, construído com base na [#configuração], e que você pode acessar pedindo para ser passado via [injeção de dependência |dependency-injection:passing-dependencies].


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

O mailer padrão é o SendmailMailer, que usa a função PHP [php:mail]. Exemplo de uso:

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

Se você quiser definir o `returnPath` e o servidor ainda o sobrescrever, use `$mailer->commandArgs = '-fMeu@email.cz'`.


SmtpMailer
----------

Para enviar e-mails através de um servidor SMTP, use `SmtpMailer`.

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

Os seguintes parâmetros adicionais podem ser passados para o construtor:

* `port` - se não definido, o padrão 25 ou 465 para `ssl` será usado
* `timeout` - timeout para a conexão SMTP
* `persistent` - usar conexão persistente
* `clientHost` - definir o cabeçalho Host do cliente
* `streamOptions` - permite definir "SSL context options":https://www.php.net/manual/en/context.ssl.php para a conexão


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

Não envia e-mails diretamente, mas medeia o envio através de um conjunto de mailers. Se um mailer falhar, ele repete a tentativa com o próximo. Se o último também falhar, ele começa novamente do primeiro.

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

Como parâmetros adicionais no construtor, podemos especificar o número de repetições e o tempo de espera em milissegundos.


DKIM
====

DKIM (DomainKeys Identified Mail) é uma tecnologia para aumentar a confiabilidade dos e-mails, que também ajuda a detectar mensagens falsificadas. A mensagem enviada é assinada com a chave privada do domínio do remetente e esta assinatura é armazenada no cabeçalho do e-mail. O servidor do destinatário compara esta assinatura com a chave pública armazenada nos registros DNS do domínio. Se a assinatura corresponder, prova-se que o e-mail realmente veio do domínio do remetente e que não foi modificado durante a transmissão da mensagem.

Você pode configurar a assinatura de e-mail para o mailer diretamente na [#configuração]. Se você não estiver usando injeção de dependência, ele é usado desta forma:

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

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


Configuração
============

Visão geral das opções de configuração para Nette Mail. Se você não estiver usando todo o framework, mas apenas esta biblioteca, leia [como carregar a configuração |bootstrap:].

Para enviar e-mails, o mailer `Nette\Mail\SendmailMailer` é usado por padrão, que não é configurado posteriormente. No entanto, podemos mudá-lo para `Nette\Mail\SmtpMailer`:

```neon
mail:
	# usa SmtpMailer
	smtp: true       # (bool) o padrão é false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) o padrão é null (tem alias 'secure')
	clientHost: ...  # (string) o padrão é $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) o padrão é false

	# contexto para conexão com o servidor SMTP, o padrão é stream_context_get_default()
	context:
		ssl:         # visão geral das opções em https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # visão geral das opções em https://www.php.net/manual/en/context.http.php
			header: ...
			...
```

Usando a opção `context › ssl › verify_peer: false`, você pode desativar a verificação do certificado SSL. **É altamente recomendável não fazer isso**, pois a aplicação se tornará vulnerável. Em vez disso, "adicione os certificados ao armazenamento":https://www.php.net/manual/en/openssl.configuration.php.

Para aumentar a confiabilidade, podemos assinar e-mails usando a [tecnologia DKIM |https://blog.nette.org/en/sign-emails-using-dkim]:

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


Serviços DI
===========

Estes serviços são adicionados ao contêiner DI:

| Nome            | Tipo                      | Descrição
|------------------------------------------------------
| `mail.mailer`	  | [api:Nette\Mail\Mailer]   | [classe que envia e-mails |#Enviando e-mail]
| `mail.signer`	  | [api:Nette\Mail\Signer]   | [Assinatura DKIM |#DKIM]


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

Enviando e-mails

Você vai enviar e-mails, como newsletters ou confirmações de pedidos? O Nette Framework fornece as ferramentas necessárias com uma API muito agradável. Vamos mostrar:

  • como criar um e-mail, incluindo anexos
  • como enviá-lo
  • como conectar e-mails e templates

Instalação

Baixe e instale a biblioteca usando o Composer:

composer require nette/mail

Criando um e-mail

Um e-mail é um objeto da classe Nette\Mail\Message. Vamos criá-lo assim:

$mail = new Nette\Mail\Message;
$mail->setFrom('Franta <franta@example.com>')
	->addTo('petr@example.com')
	->addTo('jirka@example.com')
	->setSubject('Confirmação do pedido')
	->setBody("Olá,\nseu pedido foi recebido.");

Todos os parâmetros inseridos devem estar em UTF-8.

Além de especificar o destinatário com o método addTo(), também é possível especificar o destinatário da cópia addCc(), ou o destinatário da cópia oculta addBcc(). Em todos esses métodos, incluindo setFrom(), podemos escrever o destinatário de três maneiras:

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

O corpo do e-mail escrito em HTML é passado pelo método setHtmlBody():

$mail->setHtmlBody('<p>Olá,</p><p>seu pedido foi recebido.</p>');

Você não precisa criar a alternativa de texto, o Nette a gerará automaticamente para você. E se o e-mail não tiver um assunto definido, ele tentará pegá-lo do elemento <title>.

Também é extraordinariamente fácil inserir imagens no corpo HTML. Basta passar o caminho onde as imagens estão fisicamente localizadas como segundo parâmetro, e o Nette as incluirá automaticamente no e-mail:

// adiciona automaticamente /path/to/images/background.gif ao e-mail
$mail->setHtmlBody(
	'<b>Olá</b> <img src="background.gif">',
	'/path/to/images',
);

O algoritmo que insere imagens procura por estes padrões: <img src=...>, <body background=...>, url(...) dentro do atributo HTML style e a sintaxe especial [[...]].

Enviar e-mails pode ser ainda mais fácil?

Um e-mail é como um cartão postal. Nunca envie senhas ou outras credenciais por e-mail.

Anexos

Claro, anexos podem ser inseridos no e-mail. O método addAttachment(string $file, ?string $content = null, ?string $contentType = null) é usado para isso.

// insere o arquivo /path/to/example.zip no e-mail com o nome example.zip
$mail->addAttachment('/path/to/example.zip');

// insere o arquivo /path/to/example.zip no e-mail chamado info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// insere o arquivo example.txt no e-mail com o conteúdo "Olá John!"
$mail->addAttachment('example.txt', 'Olá John!');

Templates

Se você envia e-mails HTML, é natural escrevê-los no sistema de templates Latte. Como fazer isso?

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

Arquivo email.latte:

<html>
<head>
	<meta charset="utf-8">
	<title>Confirmação do pedido</title>
	<style>
	body {
		background: url("background.png")
	}
	</style>
</head>
<body>
	<p>Olá,</p>

	<p>Seu pedido número {$orderId} foi recebido.</p>
</body>
</html>

O Nette insere automaticamente todas as imagens, define o assunto de acordo com o elemento <title> e gera uma alternativa de texto para o HTML.

Uso no Nette Application

Se você usa e-mails em conjunto com o Nette Application, ou seja, com presenters, pode querer criar links nos templates usando o atributo n:href ou a tag {link}. O Latte não os conhece por padrão, mas é muito fácil adicioná-los. O objeto Nette\Application\LinkGenerator pode criar links, e você pode acessá-lo pedindo para ser passado via injeção de dependência:

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

No template, criamos links da maneira que estamos acostumados. Todos os links criados através do LinkGenerator serão absolutos.

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

Enviando e-mail

Mailer é uma classe que garante o envio de e-mails. Implementa a interface Nette\Mail\Mailer e existem vários mailers pré-preparados disponíveis, que apresentaremos.

O framework adiciona automaticamente um serviço do tipo Nette\Mail\Mailer ao contêiner DI, construído com base na configuração, e que você pode acessar pedindo para ser passado via injeção de dependência.

SendmailMailer

O mailer padrão é o SendmailMailer, que usa a função PHP mail. Exemplo de uso:

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

Se você quiser definir o returnPath e o servidor ainda o sobrescrever, use $mailer->commandArgs = '-fMeu@email.cz'.

SmtpMailer

Para enviar e-mails através de um servidor SMTP, use SmtpMailer.

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

Os seguintes parâmetros adicionais podem ser passados para o construtor:

  • port – se não definido, o padrão 25 ou 465 para ssl será usado
  • timeout – timeout para a conexão SMTP
  • persistent – usar conexão persistente
  • clientHost – definir o cabeçalho Host do cliente
  • streamOptions – permite definir SSL context options para a conexão

FallbackMailer

Não envia e-mails diretamente, mas medeia o envio através de um conjunto de mailers. Se um mailer falhar, ele repete a tentativa com o próximo. Se o último também falhar, ele começa novamente do primeiro.

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

Como parâmetros adicionais no construtor, podemos especificar o número de repetições e o tempo de espera em milissegundos.

DKIM

DKIM (DomainKeys Identified Mail) é uma tecnologia para aumentar a confiabilidade dos e-mails, que também ajuda a detectar mensagens falsificadas. A mensagem enviada é assinada com a chave privada do domínio do remetente e esta assinatura é armazenada no cabeçalho do e-mail. O servidor do destinatário compara esta assinatura com a chave pública armazenada nos registros DNS do domínio. Se a assinatura corresponder, prova-se que o e-mail realmente veio do domínio do remetente e que não foi modificado durante a transmissão da mensagem.

Você pode configurar a assinatura de e-mail para o mailer diretamente na configuração. Se você não estiver usando injeção de dependência, ele é usado desta forma:

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

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

Configuração

Visão geral das opções de configuração para Nette Mail. Se você não estiver usando todo o framework, mas apenas esta biblioteca, leia como carregar a configuração.

Para enviar e-mails, o mailer Nette\Mail\SendmailMailer é usado por padrão, que não é configurado posteriormente. No entanto, podemos mudá-lo para Nette\Mail\SmtpMailer:

mail:
	# usa SmtpMailer
	smtp: true       # (bool) o padrão é false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) o padrão é null (tem alias 'secure')
	clientHost: ...  # (string) o padrão é $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) o padrão é false

	# contexto para conexão com o servidor SMTP, o padrão é stream_context_get_default()
	context:
		ssl:         # visão geral das opções em https://www.php.net/manual/en/context.ssl.php
			allow_self_signed: ...
			...
		http:        # visão geral das opções em https://www.php.net/manual/en/context.http.php
			header: ...
			...

Usando a opção context › ssl › verify_peer: false, você pode desativar a verificação do certificado SSL. É altamente recomendável não fazer isso, pois a aplicação se tornará vulnerável. Em vez disso, adicione os certificados ao armazenamento.

Para aumentar a confiabilidade, podemos assinar e-mails usando a tecnologia DKIM:

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

Serviços DI

Estes serviços são adicionados ao contêiner DI:

Nome Tipo Descrição
mail.mailer Nette\Mail\Mailer classe que envia e-mails
mail.signer Nette\Mail\Signer Assinatura DKIM