Mail

Enviando
Emails

Envio de e-mails

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

  • como criar um e-mail, incluindo os anexos
  • como enviá-lo
  • como combinar e-mails e modelos

Instalação

Baixe e instale o pacote usando o Composer:

composer require nette/mail

Criando e-mails

O e-mail é um objeto Nette\Mail\Message:

$mail = new Nette\Mail\Message;
$mail->setFrom('John <john@example.com>')
	->addTo('peter@example.com')
	->addTo('jack@example.com')
	->setSubject('Order Confirmation')
	->setBody("Hello, Your order has been accepted.");

Todos os parâmetros devem ser codificados em UTF-8.

Além de especificar os destinatários com o método addTo(), você também pode especificar o destinatário da cópia com addCc(), ou o destinatário da cópia cega com addBcc(). Todos esses métodos, incluindo setFrom(), aceitam o destinatário de três maneiras:

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

O corpo de um e-mail escrito em HTML é passado usando o método setHtmlBody():

$mail->setHtmlBody('<p>Hello,</p><p>Your order has been accepted.</p>');

Você não tem que criar uma alternativa de texto, Nette a gerará automaticamente para você. E se o e-mail não tiver um conjunto de assuntos, ele será retirado do <title> elemento.

As imagens também podem ser inseridas com extrema facilidade no corpo HTML de um e-mail. Basta passar o caminho onde as imagens estão fisicamente localizadas como segundo parâmetro, e a Nette as incluirá automaticamente no e-mail:

// adiciona automaticamente /caminho/para/imagens/background.gif ao e-mail
$mail->setHtmlBody(
	<b>Hello</b> <img src="background.gif">",
	/caminho/para/imagens',
);

O algoritmo de incorporação de imagem suporta os seguintes padrões: <img src=...>, <body background=...>, url(...) dentro do atributo HTML style e sintaxe especial [[...]].

O envio de e-mails pode ser ainda mais fácil?

Os e-mails são como cartões postais. Nunca envie senhas ou outras credenciais por e-mail.

Anexos

Você pode, é claro, anexar anexos ao e-mail. Use o site addAttachment(string $file, ?string $content = null, ?string $contentType = null).

// insere o arquivo /caminho/para/exemplo.zip no e-mail com o nome exemplo.zip
$mail->addAttachment('/caminho/para/exemplo.zip');

// insere o arquivo /caminho/para/exemplo.zip no e-mail sob o nome info.zip
$mail->addAttachment('info.zip', file_get_contents('/path/to/example.zip'));

// anexa novo conteúdo do arquivo exemplo.txt "Olá John!
$mail->addAttachment('example.txt', 'Olá John!');

Modelos

Se você enviar e-mails HTML, é uma ótima idéia escrevê-los no sistema de modelos Latte. Como fazer isso?

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

Arquivo email.latte:

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

	<p>Your order number {$orderId} has been accepted.</p>
</body>
</html>

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

Utilização na aplicação Nette

Se você utiliza e-mails juntamente com a Aplicação Nette, ou seja, apresentadores, você pode querer criar links em modelos usando o atributo n:href ou a tag {link}. O Latte basicamente não os conhece, mas é muito fácil adicioná-los. A criação de links pode fazer o objeto Nette\Application\LinkGenerator, que você obtém passando por ele usando a 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 modelo, o link é criado como em um modelo normal. Todos os links criados sobre o LinkGenerator são absolutos:

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

Envio de e-mails

O Mailer é a classe responsável pelo envio de e-mails. Ele implementa a interface Nette\Mail\Mailer e vários mailers prontos estão disponíveis que apresentaremos.

A estrutura adiciona automaticamente um serviço Nette\Mail\Mailer baseado na configuração do recipiente DI, que você obtém passando-o usando a 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 configurar returnPath e o servidor ainda o sobrescreve, use $mailer->commandArgs = '-fmy@email.com'.

SmtpMailer

Para enviar correio através do 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 estiver definido, será utilizado o padrão 25 ou 465 para ssl
  • timeout – tempo limite para conexão SMTP
  • persistent – usar conexão persistente
  • clientHost – designação do cliente
  • streamOptions – permite definir opções de contexto SSL para conexão

FallbackMailer

Ele não envia e-mails, mas os envia através de um conjunto de remetentes. Se um remetente falhar, ele repete a tentativa no próximo. Se o último falhar, ele começa novamente a partir do primeiro.

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

Outros parâmetros no construtor incluem o número de repetições e tempo de espera em milissegundos.

DKIM

O DKIM (DomainKeys Identified Mail) é uma tecnologia de e-mail confiável 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. Combinando a assinatura, é mostrado que o e-mail realmente originou-se do domínio do remetente e que a mensagem não foi modificada durante a transmissão da mensagem.

Você pode configurar o mailer para assinar o e-mail na configuração. Se você não usa injeção de dependência, ela é usada da seguinte forma:

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

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

Configurando

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

Por padrão, o mailer Nette\Mail\SendmailMailer é usado para enviar e-mails, que não está mais configurado. Entretanto, podemos mudá-lo para Nette\Mail\SmtpMailer:

mail:
	# usar SmtpMailer
	smtp: true       # (bool) default to false

	host: ...        # (string)
	port: ...        # (int)
	username: ...    # (string)
	password: ...    # (string)
	timeout: ...     # (int)
	encryption: ...  # (ssl|tls|null) padrão a nulo (tem pseudônimo 'seguro')
	clientHost: ...  # (string) padrão de $_SERVER['HTTP_HOST']
	persistent: ...  # (bool) falha em falso

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

Você pode desativar a autenticação do certificado SSL usando a opção context › ssl › verify_peer: false. É ** fortemente recomendado não fazer** isso, pois isso tornará a aplicação vulnerável. Em vez disso, adicionar certificados à loja de confiança.

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

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

Serviços DI

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

Nome Tipo Descrição
mail.mailer Nette\Mail\Mailer classe de envio de e-mail
mail.signer Nette\Mail\Signer Assinatura DKIM
versão: 4.0