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 parassl
será usadotimeout
– timeout para a conexão SMTPpersistent
– usar conexão persistenteclientHost
– definir o cabeçalho Host do clientestreamOptions
– 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 |