Como Enviar Emails em HTML em PHP

On maio 31, 2024
22min read
Ketevan Bostoganashvili Technical Content Writer @Mailtrap
PHP send HTML email

PHP tem várias opções para enviar emails HTML: a função PHP mail(), PHPMailer, ou SymfonyMailer. No entanto, as duas últimas são as opções mais populares e recomendadas.

Por quê? Porque a função mail() do PHP tem várias limitações, incluindo a incapacidade de adicionar anexos ou enviar emails usando o servidor SMTP. Vou detalhar as limitações abaixo.

Neste tutorial, vou mostrar como construir e enviar emails HTML em PHP usando a função mail(), PHPMailer e SymfonyMailer. Também mostrarei como aproveitar o SDK do Mailtrap para enviar belos emails HTML em PHP. Vamos lá!

Enviar emails HTML usando a função mail() do PHP

Vou começar com mail(), pois é uma função nativa no PHP. Com ela, você pode enviar emails de texto simples e HTML simples. Primeiro, listarei suas limitações e depois fornecerei o código para enviar emails HTML.

Limitações da função mail() do PHP

A função mail() do PHP pode ser simples, mas há várias coisas que ela não permite fazer:

  • Você não poderá adicionar anexos sem configurações complexas;
  • Você não poderá incorporar imagens diretamente no email como anexos que podem ser referenciados no conteúdo HTML via CID (Content ID);
  • Você terá dificuldade em enviar emails para vários destinatários, pois a função mail() abre e fecha o socket SMTP para cada email enviado. Isso pode ser demorado e consumir muitos recursos;
  • Você terá dificuldade em se conectar a servidores SMTP de terceiros, pois a função mail() envia emails através do servidor local. E, pelo mesmo motivo, você provavelmente enfrentará problemas de entregabilidade (mesmo se você tiver configurado corretamente os SPF, DKIM e DMARC e seguido as melhores práticas de entregabilidade).

Considerando as limitações e preocupações de segurança, a função mail() não é uma opção preferível para enviar emails em PHP. Mas, se você ainda quiser usá-la, mostrarei como na próxima seção. Leia este post no blog ou assista a este vídeo para uma explicação detalhada sobre o envio de emails em PHP.

Enviar um email HTML simples

A função mail() incorporada requer quatro argumentos: o endereço de email do destinatário, o assunto do email, a mensagem, e os cabeçalhos adicionais. Os cabeçalhos adicionais permitem definir o cabeçalho Content-type e especificá-lo como text/html.

Às vezes, cabeçalhos extras são usados para especificar o cabeçalho 'X-Mailer: PHP/' . phpversion(). Isso pode ser útil para depuração, mas pode revelar as configurações do seu servidor. Por essa razão, decidi omiti-lo.

<?php

$to = 'contacto@exemplo.com';
$subject = 'Oi!';

$headers['From'] = 'remetente@exemplo.com';
$headers['MIME-Version'] = 'MIME-Version: 1.0';
$headers['Content-type'] = 'text/html; charset=iso-8859-1'

$message = '
<html>
<head>
    <title>Alerta para Rever o Pedido</title>
</head>
<body>
    <p>Aqui estão os casos que requerem sua revisão em Dezembro:</p>
    <table>
        <tr>
            <th>Título do caso</th><th>Categoria</th><th>Estado</th><th>Data limite</th>
        </tr>
        <tr>
            <td>Caso 1</td><td>Desenvolvimento</td><td>pendente</td><td>Dez-20</td>
        </tr>
        <tr>
            <td>Caso 2</td><td>DevOps</td><td>pendente</td><td>Dez-21</td>
        </tr>
    </table>
</body>
</html>
';

$result = mail($to, $subject, $message, $headers);

if ($result) {
    echo 'Sucesso!' . PHP_EOL;
} else {
    echo 'Erro.' . PHP_EOL;
}

Eu também adicionei tratamento de erros. A instrução if verifica se o email foi enviado com sucesso e fornece feedback com base no resultado.

Executei este código PHP com o comando php send-mail.php e recebi a mensagem Sucesso!.

Mensagem de sucesso recebida após a execução bem-sucedida do código PHP

Tenha em mente que, apesar da mensagem de sucesso, o email ainda pode não chegar na caixa de entrada indicada. Isso devido às limitações que listamos acima. Além disso, o código funcionará apenas com configurações específicas (com um servidor local ou com uma configuração do WordPress que não requer conexões SMTP de terceiros via TLS).

Enviar um email HTML com imagens (hospedando imagens no servidor)

Uma opção para incorporar imagens ao usar a função mail() é hospedar as imagens no servidor. Ao contrário do base64, esse método não aumenta o tamanho do email.

Veja como fazer isso:

  1. Carregue a imagem no seu servidor web. Certifique-se de que ela esteja carregada em um local publicamente acessível.
  2. Referencie a imagem no seu conteúdo HTML usando a tag <img> e seu URL absoluto:
<img src="https://www.seudominio.com/imagens/sua-imagem.jpg" alt="Embedded Image">
  1. Envie o email com a função mail() como fizemos no exemplo anterior.

O snippet de código completo ficará assim:

<?php

$to = 'destinatario@exemplo.com';
$subject = 'Email com Imagem Incorporada';
$message = '
<html>
<head>
  <title>Email com Imagem Incorporada</title>
</head>
<body>
  <p>Aqui está uma imagem incorporada neste email:</p>
  <img src="https://www.seudominio.com/imagens/sua-imagem.jpg" alt="Embedded Image">
</body>
</html>
';

$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

$headers .= 'From: <remetente@exemplo.com>' . "\r\n";
$headers .= 'Reply-To: <remetente@exemplo.com>' . "\r\n";

if(mail($to, $subject, $message, $headers)) {
    echo "Email enviado com sucesso.";
} else {
    echo "Envio do email falhou.";
}
?>

Enviar um email HTML com imagens (incorporando com base64)

Outra opção é codificar a imagem com base64. Isso transformará os dados binários da imagem em uma string de texto, e poderemos incorporá-la ao código HTML usando a tag <img>.

Mas, antes de passar para a incorporação, adicionarei uma verificação simples de erro para garantir que o arquivo exista e seja legível. Depois, vou codificá-lo.

<?php
// Verifique se o arquivo de imagem existe e é legível
$imagePath = 'path/to/imagem.jpg';
if (file_exists($imagePath) && is_readable($imagePath)) {
    // Converta sua imagem para string base64
    $imageData = base64_encode(file_get_contents($imagePath));
} else {
    echo "Ficheiro de imagem não encontrado ou não acessívele.";
    exit; // Interrompa a execução do script se a imagem não for acessível
}

No script acima, o código será executado apenas se ambas as condições forem atendidas, ou seja, o arquivo de imagem existir e for legível.

O próximo passo é construir o conteúdo HTML como no exemplo anterior, mas desta vez, adicionarei a tag <img>.

$message = '
<html>
<head>
<title>Título do Seu Email Aqui</title>
</head>
<body>
<p>Aqui está o conteúdo do seu email.</p>
<img src="data:image/jpeg;base64,' . $imageData . '" alt="Description of Image">
</body>
</html>
';

Finalmente, configurarei os cabeçalhos e enviarei um email. Os cabeçalhos devem ser separados por CRLF (\r\n). O snippet de código completo ficará assim:

<?php
// Verifique se o ficheiro de imagem existe e é legível
$imagePath = 'path/to/imagem.jpg';
if (file_exists($imagePath) && is_readable($imagePath)) {
    // Convert your image to base64 string
    $imageData = base64_encode(file_get_contents($imagePath));
} else {
    echo "Arquivo de imagem não encontrado ou não acessível.";
    exit; // Interrompa a execução do script se a imagem não for acessível
}

// Construa o conteúdo do email HTML
$message = '
<html>
<head>
<title>Título do seu Email</title>
</head>
<body>
<p>Aqui está o conteúdo do seu email.</p>
<img src="data:image/jpeg;base64,' . $imageData . '" alt="Description of Image">
</body>
</html>
';

// Configure os cabeçalhos
$headers = [
    "MIME-Version: 1.0",
    "Content-type: text/html; charset=UTF-8",
    'From: Seu Nome <remetente@exemplo.com>',
    'Cc: Outro Nome <outro-email@exemplo.com>',
];

// Envio do email
if (mail('destinatario@exemplo.com', 'Assunto do Seu Email', $message, implode("\r\n", $headers))) {
    echo "Email enviado com sucesso.";
} else {
    echo "Falha ao enviar email.";
}
?>

Tenha em mente que este método aumenta significativamente o tamanho do email. Maior tamanho de email pode levar a alguns problemas:

  1. Tempos de carregamento mais lentos;
  2. Servidores de email rejeitando emails devido ao seu tamanho maior;
  3. Provedores de email bloqueando imagens codificadas em base64 por razões de segurança.

Enviar emails HTML usando PHPMailer

Uma maneira melhor de enviar emails HTML em PHP é usando o PHPMailer. Este pacote resolve as limitações da função mail() nativa. Possui funcionalidades como:

  • Autenticação SMTP;
  • Suporte para protocolos TLS e SSL;
  • Incorporação de imagens;
  • Adição de anexos;
  • Capacidade de se conectar a servidores SMTP externos;
  • E, mais importante (pelo menos para este artigo), a capacidade de enviar emails em texto e HTML.

Primeiro, instalarei o pacote adicionando a seguinte linha ao arquivo composer.json:

"phpmailer/phpmailer": "^6.9.1"

Alternativamente, você pode executar o comando composer require phpmailer/phpmailer.

Para enviar e entregar emails HTML com PHPMailer, usarei um provedor SMTP externo – Email API/SMTP do Mailtrap, que é uma solução de envio com altas taxas de entregabilidade por defeito.

O Email API/SMTP fornece streams separados para emails em massa e transacionais para manter uma entregabilidade alta e estável. Embora tenha um SDK oficial para PHP, vou focar-me no servidor SMTP por enquanto.

Enviar uma mensagem HTML básica

Enviar uma mensagem HTML básica usando PHPMailer é bem simples. Primeiro, comece seu novo projeto PHP com o seguinte código:

<?php
use PHPMailer\PHPMailer\PHPMailer;

E inclua o arquivo autoload.php gerado pelo Composer.

require 'path/to/composer/vendor/autoload.php';

Crie uma nova instância da classe PHPMailer e configure as configurações SMTP.

$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'live.smtp.mailtrap.io';
$mail->SMTPAuth = true;
$mail->Username = '1a2b3c4d5e6f7g';
$mail->Password = '1a2b3c4d5e6f7g';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

Para este passo, tive que ir à minha conta Mailtrap e obter as credenciais necessárias. Já adicionei e verifiquei o domínio de envio, mas se você ainda não fez isso, confira o artigo de configuração de domínio de envio para instruções detalhadas.

Depois que o domínio for verificado, vá para Sending Domains, clique no domínio verificado e abra a aba SMTP/API Settings. Lá, você verá o Transactional Stream e o Bulk Stream. Neste caso, optarei por um Transactional Stream e copiarei as credenciais abaixo.

Isso é como o trecho de código acima ficará uma vez configurado com as configurações SMTP do Mailtrap.

$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'live.smtp.mailtrap.io';
$mail->SMTPAuth = true;
$mail->Username = 'api';
$mail->Password = 'SEU_TOKEN_API'
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

Especifique os cabeçalhos. Indique o endereço de email de envio contendo o domínio verificado usando o método setFrom. Defina o endereço de email do destinatário com o método addAddress. Em seguida, adicione a linha de assunto usando a propriedade Subject.

$mail->setFrom(address: 'remetente@exemplo.com', name: 'Kate');
$mail->addAddress(address: 'destinatario@exemplo.com', name: John);
$mail->Subject = 'Seu Assunto do Email!';

Defina o formato do email para HTML usando a propriedade isHTML e adicione o conteúdo HTML. Use a propriedade AltBody para indicar a versão em texto do email.

$mail->isHTML(isHtml: TRUE);
$mail->Body = '<html>Oi, temos o prazer de <br>confirmar sua reserva.<br>Por favor confira o documento em anexo.</html>';
$mail->AltBody = 'Oi, temos o prazer de confirmar sua reserva. Por favor confira o documento em anexo.';

Finalmente, envie o email usando o método send.

if (!$mail->send()) {
    echo 'A mensagem não pôde ser enviada.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'A mensagem foi enviada.';
}

Confira o exemplo completo abaixo:

<?php
use PHPMailer\PHPMailer\PHPMailer;

require 'path/to/composer/vendor/autoload.php';

$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'live.smtp.mailtrap.io';
$mail->SMTPAuth = true;
$mail->Username = 'api';
$mail->Password = 'SEU_TOKEN_API';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

$mail->setFrom('remetente@exemplo.com', 'Kate');
$mail->addAddress('destinatario@exemplo.com', 'John');
$mail->Subject = 'Seu Assunto do Email!';

$mail->isHTML(true);
$mail->Body = '<html>Oi, temos o prazer de <br>confirmar sua reserva.<br>Por favor confira os detalhes.</html>';
$mail->AltBody = 'Oi, temos o prazer de confirmar sua reserva. Por favor confira os detalhes.';

if (!$mail->send()) {
    echo 'A mensagem não pôde ser enviada.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'A mensagem foi enviada.';
}
?>

Execute o script com o comando php send–mail-php-mailer.php. A mensagem de email HTML deve aparecer na caixa de entrada do destinatário se você fez tudo corretamente.

Enviar um email HTML com uma imagem incorporada

Quando se trata de incorporação, você tem algumas opções: codificação base64 (semelhante a como fizemos com o script PHP nativo), CID (Content ID) e vinculação de imagens hospedadas em um servidor web.

Cada método tem suas desvantagens, mas o CID ainda é uma opção recomendada. Ele envolve anexar uma imagem e referenciá-la no HTML com CID.

Então, ao código PHP anterior, adicionarei o método addEmbeddedImage. Passarei o caminho da imagem e o CID para ele.

$mail->addEmbeddedImage('path/to/imagem.jpg', 'image_cid'); 

Em seguida, incluirei no atributo src da tag <img>.

$mail->isHTML(true); // Definir formato do email para HTML
$mail->Subject = 'Aqui está o assunto';
$mail->Body    = '
<!DOCTYPE html>
<html>
<head>
    <title>Sua Confirmação de Reserva</title>
</head>
<body>
    <p>Olá, estamos felizes em <br>confirmar sua reserva.<br>Por favor, verifique os detalhes:</p>
    <img src="cid:image_cid">
</body>
</html>';

Enviar um email HTML com anexos

Para incluir um anexo no seu email formatado em HTML, basta adicionar as seguintes linhas de código após a parte HTML/texto:

$attachmentPath = './confirmations/yourbooking.pdf';
if (file_exists($attachmentPath)) {
    $mail->addAttachment($attachmentPath, name: 'suareserva.pdf');
}

Se você quiser adicionar vários anexos, repita o código acima quantas vezes for necessário. Não se esqueça de especificar os caminhos exatos para cada arquivo.

Enviar emails HTML para vários destinatários

Com o PHPMailer, você pode enviar facilmente emails HTML para vários destinatários. Vou percorrer um array de destinatários e usar o método addAddress() para cada um.

$recipients = [
    ['email' => 'destinatario1@exemplo.com', 'name' => 'John Doe'],
    ['email' => 'destinatario2@exemplo.com', 'name' => 'Jane Doe'],
    // Adicione mais destinatários conforme necessário
];

foreach ($recipients as $recipient) {
    $mail->addAddress($recipient['email'], $recipient['name']);
}

$recipients é um array que contém os endereços de email e nomes de todos os destinatários. O loop foreach itera sobre este array, adicionando cada destinatário ao email. Quando eu chamar o método send(), o email será enviado para cada destinatário adicionado.

O restante do exemplo de código será essencialmente o mesmo que no exemplo anterior.

Se você quiser enviar outros tipos de emails, leia o tutorial completo sobre PHPMailer. E confira este post no blog para aprender como enviar emails com PHPMailer e o servidor SMTP do Gmail.

Enviar emails HTML usando o Mailtrap PHP Client

Uma maneira fácil de construir e enviar emails HTML complexos em PHP é com o Mailtrap PHP Client. É totalmente compatível com os frameworks Laravel e Symfony e permite que você escolha o cliente HTTP desejado.

Com o SDK PHP do Mailtrap, você também pode enviar emails HTML em PHP usando templates. Você pode armazenar os templates no Mailtrap e referenciá-los através da API. Leia este artigo para mais informações sobre recursos e usos de templates.

Nota: No momento da escrita, templates estão disponíveis apenas para emails transacionais. Em breve, também estarão disponíveis para emails em massa.

Enviar emails HTML sem templates

Primeiro, vou mostrar como enviar emails HTML sem templates. Mas, antes de enviar os emails, preciso obter a chave da API do Mailtrap e armazená-la de forma segura no arquivo .env.

Para acessar sua chave da API, em sua conta Mailtrap, vá para SettingsAPI Tokens e clique no botão Add Token.

Acessando tokens da API na conta Mailtrap Email Sending

Escolha o domínio verificado do qual você deseja enviar emails, adicione o nome desejado e clique em Save.

Criando um token da API no Mailtrap Email Sending

O token da API aparecerá na página API Tokens. Basta copiá-lo. Retorne ao seu projeto PHP e crie um arquivo .env no diretório raiz. Adicione sua chave da API do Mailtrap a este arquivo assim:

# .env file
MAILTRAP_API_KEY=sua_chave_api_do_mailtrap

Em seguida, atualize seu arquivo .gitignore para excluir o arquivo .env do controle de versão e proteger dados sensíveis.

Neste ponto, podemos instalar o Mailtrap PHP Client. Se você estiver usando o cliente HTTP Symfony, use este comando:

composer require railsware/mailtrap-php symfony/http-client nyholm/psr7 

Para o cliente HTTP Guzzle, instale o pacote executando a seguinte linha de código:

composer require railsware/mailtrap-php guzzlehttp/guzzle php-http/guzzle7-adapter 

Uma vez feito isso, copie o código-fonte do GitHub e ajuste-o com o conteúdo HTML que você deseja usar. Com este SDK, você pode definir o endereço reply-to, adicionar destinatários de Cc ou Bcc, enviar emails em HTML e em texto simples, incorporar imagens, definir cabeçalhos personalizados, e indicar a categoria (este último é útil para estatísticas).

<?php

use Mailtrap\Config;
use Mailtrap\EmailHeader\CategoryHeader;
use Mailtrap\EmailHeader\CustomVariableHeader;
use Mailtrap\Helper\ResponseHelper;
use Mailtrap\MailtrapClient;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Header\UnstructuredHeader;

require __DIR__ . '/vendor/autoload.php';

// seu token da API aqui https://mailtrap.io/api-tokens
$apiKey = getenv('MAILTRAP_API_KEY');
$mailtrap = new MailtrapClient(new Config($apiKey));

$email = (new Email())
    ->from(new Address('example@your-domain-here.com', 'Mailtrap Test'))
    ->replyTo(new Address('reply@your-domain-here.com'))
    ->to(new Address('email@example.com', 'Jon'))
    ->priority(Email::PRIORITY_HIGH)
    ->cc('mailtrapqa@example.com')
    ->addCc('staging@example.com')
    ->bcc('mailtrapdev@example.com')
    ->subject(‘Melhores dicas para criar emails HTML')
    ->text(‘Oi! Aprenda as melhores práticas para criar emails em HTML e experimentar templates pré-feitos. O guia do Mailtrap sobre Como Criar Emails HTML está já no nosso blogue.')
    ->html(
        '<html>
        <body>
        <p><br>Oi</br>
        Aprenda as melhores práticas para criar emails em HTML e experimentar templates pré-feitos.</p>
        <p>O <a href="https://mailtrap.io/pt/blog/build-html-email/">guia do Mailtrap sobre Como Criar Emails HTML</a> já está no nosso blogue</p>
        <img src="cid:logo">
        </body>
    </html>'
    )
    ->embed(fopen('https://mailtrap.io/wp-content/uploads/2021/04/mailtrap-new-logo.svg', 'r'), 'logo', 'image/svg+xml')
    ;
   
    // Cabeçalhos
    $email->getHeaders()
    ->addTextHeader('X-Message-Source', 'domain.com')
    ->add(new UnstructuredHeader('X-Mailer', 'Mailtrap PHP Client')) // o mesmo que addTextHeader
    ;
   
    // Variáveis Personalizadas
    $email->getHeaders()
    ->add(new CustomVariableHeader('user_id', '45982'))
    ->add(new CustomVariableHeader('batch_id', 'PSJ-12'))
    ;
   
    // Categoria (deve ser apenas uma)
    $email->getHeaders()
    ->add(new CategoryHeader('Integration Test'))
    ;
   
try {
    $response = $mailtrap->sending()->emails()->send($email); // API de envio de email (real)
   
    var_dump(ResponseHelper::toArray($response)); // corpo (array)
} catch (Exception $e) {
    echo 'Exceção capturada: ',  $e->getMessage(), "\n";
}

Pro Tip: Antes de enviar um email para os destinatários, envie um email para a caixa de entrada virtual do Email Testing do Mailtrap usando o SDK do PHP para inspecionar e depurar seus emails HTML. Minha equipe e eu sempre usamos essa opção para garantir que a integração funcione e o template seja renderizado corretamente. Vou falar sobre testes em mais detalhes nesta seção.

Enviar emails HTML com templates

Se você prefere usar um template HTML, deve primeiro criá-lo no Mailtrap e depois chamá-lo com o SDK. Veja como:

  1. Na sua conta Mailtrap, vá para Email API/SMTPEmail Templates, e clique no botão Create New Template.
Criando um template no Mailtrap Email Sending
  1. Selecione o domínio para o qual deseja criar o template, escolha o template pronto ou selecione Start from scratch, e clique em Create Template.
Escolhendo o formato de template desejado no Mailtrap Email Sending
  1. Na aba Details, especifique a Email Category e adicione o nome do template. Em seguida, vá para o Code Editor e modifique o template ou cole o seu próprio.
Template de email de boas-vindas no Mailtrap Email Sending
  1. Lembre-se de que os Templates de Email do Mailtrap operam no motor handlebars e suportam variáveis. Isso significa que você pode adicionar, por exemplo, {{user_name}} ao seu template e passar “John” como o valor de “user_name” via API.
  2. Quando o template estiver pronto, vá para a aba Integrations e selecione PHP no menu dropdown. Você verá uma configuração de amostra que usa o SDK do PHP e já contém suas credenciais.

Para um template de Email de Boas-Vindas, isso é como o código se parecerá:

<?php

use Mailtrap\Config;
use Mailtrap\Helper\ResponseHelper;
use Mailtrap\MailtrapClient;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Mailtrap\EmailHeader\Template\TemplateUuidHeader;
use Mailtrap\EmailHeader\Template\TemplateVariableHeader;

require __DIR__ . '/vendor/autoload.php';

$apiKey = 'sua_api_do_mailtrap';
$mailtrap = new MailtrapClient(new Config($apiKey));

$email = (new Email())
    ->from(new Address('remetente@seu-dominio.com', 'Equipa Mailtrap'))
    ->to(new Address("destinatario@exemplo.com"))
;

$email->getHeaders()
    ->add(new TemplateUuidHeader('your_template_Uuid'))
    ->add(new TemplateVariableHeader('user_name', 'John Doe'))
    ->add(new TemplateVariableHeader('next_step_link', 'https://mailtrap.io/''))
    ->add(new TemplateVariableHeader('get_started_link', 'https://mailtrap.io/'))
    ->add(new TemplateVariableHeader('onboarding_video_link', 'link_de_um_video'))
;

$response = $mailtrap->sending()->emails()->send($email);

var_dump(ResponseHelper::toArray($response));

Claro, antes de enviar o template para os destinatários, você pode visualizá-lo e enviar um email de teste para si mesmo.

Enviar emails HTML usando SymfonyMailer

O último método de envio que cobrirei neste artigo é o SymfonyMailer. É o componente de envio de emails do framework Symfony (um framework PHP popular para desenvolvimento web). SymfonyMailer permite que você:

  • Envie emails em formato HTML;
  • Integre seu projeto com provedores de envio de terceiros;
  • Use templates Twig;
  • Use inliner CSS;
  • Adicione anexos. 

Enviar uma mensagem HTML básica

Antes de começarmos a construir o corpo da mensagem, precisamos instalar o SymfonyMailer. Execute o seguinte comando:

$ composer require symfony/mailer 

O próximo passo é configurar o transporte, que é o método que será usado para entregar seus emails. Symfony oferece três transportes incorporados:

  • SMTP que pode ser configurado com qualquer servidor SMTP de terceiros;
  • Sendmail que usa o binário sendmail local;
  • E Native que usa o binário sendmail e as opções configuradas no sendmail_path do php.ini. Se o sendmail_path não estiver configurado, o mailer irá recorrer às configurações SMTP e smtp_port do php.ini (aplica-se a hosts Windows).

E há vários transportes de terceiros para vários provedores de serviços de email.

Usarei o transporte SMTP com o servidor SMTP do Email API/SMTP do Mailtrap. Mais uma vez, precisaremos obter as credenciais da conta Mailtrap e configurar MAILER_DSN no arquivo .env.

MAILER_DSN=smtp://api:suasenha@live.smtp.mailtrap.io:587/?encryption=ssl&auth_mode=login

Uma vez que o transporte esteja configurado, podemos começar a construir a mensagem.

Primeiro, configure os namespaces necessários assim:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;

Em seguida, use a classe MailerController que se estende a AbstractController. Especifique a rota, que chamará o método index quando você lhe fizer uma solicitação.

class MailerController extends AbstractController
{
    #[Route('/mailer', name: 'app_mailer')]
    public function index(MailerInterface $mailer): Response
    {

Depois, construirei a mensagem com o objeto Email. Não usarei um template desta vez, então especificarei um corpo HTML. Vamos dar uma olhada no código completo para o email:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;

class MailerController extends AbstractController
{
    #[Route('/mailer', name: 'app_mailer')]
    public function index(MailerInterface $mailer): Response
    {
        $email = (new Email())
            ->from('mailtrap@exemplo.com')
            ->to(new Address('newuser@exemplo.com'))
            ->cc('mailtrapqa@exemplo.com')
            ->addCc('staging@exemplo.com')
            ->bcc('mailtrapdev@exemplo.com')
            ->replyTo('mailtrap@exemplo.com')
            ->subject('Aqui está o assunto')
            ->text('Oi! Aprenda as melhores práticas para criar emails HTML e experimentar templates pré-feitos. O guia do Mailtrap Como Criar Emails em HTML está já no nosso blogue')
            ->html('<html>
                        <body>
                            <p>Oi!<br>
                            Aprenda as melhores práticas para criar emails HTML e experimentar templates pré-feitos.</p>
                            <p>O <a href="https://blog.mailtrap.io/pt/build-html-email/">guia do Mailtrap Como Criar Emails em HTML</a> está já no nosso blogue</p>
                        </body>
                    </html>');

        $mailer->send($email);

        return new Response(
            content: 'Email enviado'
        );
    }
}

Enviar um email HTML com uma imagem incorporada

Em termos de incorporação, o SymfonyMailer suporta três métodos: incorporar uma imagem de um recurso PHP, incorporar uma imagem hospedada localmente ou em um servidor e incorporá-la com anexos CID. Veja como cada um desses métodos seria:

$email = (new Email())
    // ...
    //imagem de um recurso PHP, por exemplo, GD
    ->embed(fopen('/path/to/novologo.png', 'r'), 'logo')
    //imagem hospedada localmente ou em algum recurso externo
    ->embedFromPath('/path/to/novacover.png', 'new-cover-image')
    //anexo CID
    ->html('<img src="cid:logo"> ... <img src="cid:new-cover-image"> ...');

Enviar um email com template HTML

Como mencionei acima, o SymfonyMailer suporta templates Twig. Estes são integrados ao componente MIME. Templates Twig têm vários recursos úteis, incluindo a o inline de CSS e a integração direta com frameworks HTML/CSS.

Primeiro, crie um template e salve-o como um arquivo .twig. Instruções detalhadas sobre como criar templates Twig estão disponíveis aqui.

Em seguida, use a classe TemplatedEmail, que se estende à classe Email para adicionar novos métodos para templates Twig. Em vez de ->html e corpo HTML, adicione ->htmlTemplate('path/experiment.html.twig'). Não se esqueça que, claro, você deve usar um caminho real para o template.

O Mailtrap PHP SDK funciona tanto com Symfony quanto com Laravel, o que significa que você pode usar Templates de Email do Mailtrap em vez de Twig.

Enviar emails HTML para vários destinatários

Enviar emails para vários destinatários é bem simples também. Você pode fazer múltiplas chamadas to ou criar um array de objetos Address. Eu optei pelo último e modifiquei o snippet de código anterior desta forma:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Routing\Annotation\Route;

class MailerController extends AbstractController
{
    #[Route('/mailer', name: 'app_mailer')]
    public function index(MailerInterface $mailer): Response
    {
        // Definir os destinatários
        $recipients = [
            new Address('firstuser@exemplo.com', ‘Primeiro Usuário'),
            new Address('seconduser@exemplo.com', 'Segundo Usuário'),
            // ... Adicione mais destinatários conforme necessário
        ];

        $email = (new Email())
            ->from('mailtrap@exemplo.com')
            // Use o array de destinatários para o campo 'To'
            ->to(...$recipients) // O '...' é o operador de espalhamento, que desempacota os elementos do array
            ->cc('mailtrapqa@exemplo.com')
            ->addCc('staging@exemplo.com')
            ->bcc('mailtrapdev@exemplo.com')
            ->replyTo('mailtrap@exemplo.com')
            ->subject('Aqui está o assunto')
            ->text('Oi! Aprenda as melhores práticas para criar emails HTML e experimentar templates pré-feitos. O guia do Mailtrap Como Criar Emails em HTML está já no nosso blogue')
            ->html('<html>
                        <body>
                            <p>Oi!<br>
                            Aprenda as melhores práticas para criar emails HTML e experimentar templates pré-feitos.</p>
                            <p>O <a href="https://blog.mailtrap.io/pt/build-html-email/">guia do Mailtrap Como Criar Emails em HTML</a> está já no nosso blogue</p>
                        </body>
                    </html>');

        $mailer->send($email);

        return new Response(
            'Email enviado'
        );
    }
}

Enviar um email HTML com anexos

Finalmente, vamos ver como você pode enviar emails com anexos. Este processo é semelhante ao de incorporar imagens. Você tem três opções:

  • Usar attachFromPath() para incluir arquivos locais;
  • Usar attachFromPath() para incluir arquivos de um link externo;
  • E usar attach() para adicionar arquivos de um recurso PHP.

Aqui estão os exemplos para cada opção:

$email = (new Email())
    // ...
// arquivo local
    ->attachFromPath('/path/to/suaconfirmacao.pdf')
// URL externa - certifique-se de que allow_url_fopen está habilitado na sua instalação do PHP
->attachFromPath('http://mailtrap.io/path/to/suaconfirmacao', 'Sua Confirmação', 'application/msword')
// recurso PHP
  ->attach(fopen('/path/to/suaconfirmacao.pdf', 'r'));

Enviar emails HTML de um formulário HTML com PHP como backend

Se você quiser que seu formulário de contato PHP envie automaticamente emails HTML, você precisa configurar o script do lado do servidor (PHP), validação JavaScript (com validate.js) e o próprio formulário HTML.

Para instruções detalhadas sobre como construir um formulário HTML e enviar emails a partir dele, leia este artigo. Aqui, deixarei apenas um script que coleta os dados do formulário de contato, os valida e envia um email HTML para o endereço de email indicado.

Como eu queria que o formulário de contato enviasse um email HTML em vez de uma mensagem de texto, defini isHTML como true e adicionei conteúdo HTML.

<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

$errors = [];
$errorMessage = '';
$successMessage = '';
$siteKey = 'SUA_CHAVE_RECAPTCHA_DO_SITE';
$secret = 'SUA_CHAVE_SECRETA_RECAPTCHA';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = sanitizeInput ($_POST['name']);
    $email = sanitizeInput ($_POST['email']);
    $message = sanitizeInput ($_POST ['message']);
    $recaptchaResponse = sanitizeInput ($_POST['g-recaptcha-response']);

    $recaptchaUrl = "https://www.google.com/recaptcha/api/siteverify?secret={$secret]&response={$recaptchaResponse]";
    $verify = json_decode(file_get_contents($recaptchaUrl));

    if (!$verify->success) {
        $errors[] = 'Recaptcha falhou';
    }
    if (empty($name)) {
        $errors[] = 'Nome está vazio';
    }
    if (empty($email)) {
        $errors[] = 'Email está vazio';
    } else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errors[] = 'Email é inválido';
    }
    if (empty($message)) {
        $errors[] = 'Mensagem está vazia';
}

    if (!empty($errors)) {
        $allErrors = join('<br/>', $errors);
        $errorMessage = "<p style='color: red;'>{$allErrors}</p>";
    } else {
        $toEmail = 'meuemail@exemplo.com';
        $emailSubject = 'Novo email do seu formulário de contato';

        // Crie uma nova instância do PHPMailer
      $mail = new PHPMailer(true);
      try {
            // Configure a instância do PHPMailer
            $mail->isSMTP();
            $mail->Host = 'live.smtp.mailtrap.io';
            $mail->SMTPAuth = true;
            $mail->Username = 'api';
            $mail->Password = 'sua_senha_smtp';
            $mail->SMTPSecure = 'tls';
            $mail->Port = 587;
       
            // Defina o remetente, destinatário, assunto e corpo da mensagem
            $mail->setFrom($email);
            $mail->addAddress($toEmail);
            $mail->Subject = $emailSubject;
            $mail->isHTML(true);
            $mail->Body = "<p>Nome: {$name}</p><p>Email: {$email}</p><p>Mensagem: {$message}</p>";
       
            // Envie a mensagem
            $mail->send();
            $successMessage = "<p style='color: green;'>Obrigado por entrar em contato :)</p>";
      } catch (Exception $e) {
            $errorMessage = "<p style='color: red;'>Oops, algo deu errado. Por favor, tente novamente mais tarde</p>";
      }
    }
}

function sanitizeInput($input) {
    $input = trim($input);
    $input = stripslashes($input);
    $input = htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
    return $input;
}
?>

<html>
<body>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<form action="/" method="post" id="contact-form">
    <h2>Contact us</h2>
    <?php echo (!empty($errorMessage) ? $errorMessage : ''); ?>
    <?php echo (!empty($successMessage) ? $successMessage : ''); ?>
    <p>
        <label>Nome:</label>
        <input name="name" type="text" required />
    </p>
    <p>
        <label>Endereço de Email:</label>
        <input style="..." name="email" type="email" required />
    </p>
    <p>
        <label>Mensagem:</label>
        <textarea name="message" required></textarea>
    </p>
    <p>
        <button class="g-recaptcha" type="submit" data-sitekey="<?php echo $siteKey ?>" data-callback="onRecaptchaSuccess">
            Enviar
        </button>
    </p>
</form>

<script>
    function onRecaptchaSuccess() {
        document.getElementById('contact-form').submit();
    }
</script>
</body>
</html>

Testar emails HTML em PHP antes de enviar: por quê e como

Você já passou horas criando um email HTML e configurando o código apenas para que ele pareça tão confuso como um desenho feito por uma criança? Eu certamente já, mais de uma vez, se ouso admitir. Isso é especialmente problemático ao enviar emails HTML com imagens incorporadas ou anexos.

Imagens podem ser bloqueadas, anexos podem não ser anexados, ou seus emails podem acabar na temida pasta de spam. Para evitar tudo isso, a melhor prática é testar seus emails antes de enviá-los para os destinatários. Eu diria que é obrigatório se você não quiser perder clientes.

Você pode testar facilmente seus emails com uma ferramenta de teste dedicada, como o Email Testing do Mailtrap. Juntamente com o Email API/SMTP, o Email Testing faz parte da Plataforma de Email Delivery do Mailtrap.

O Email Testing é um Sandbox de Email que apanha todo o tráfego SMTP e permite que você inspecione e depure emails em staging sem enviar spam aos destinatários. Você pode integrá-lo usando as credenciais SMTP ou usar os SDKs oficiais.

SMTP

Para integrar o Email Testing usando um servidor SMTP, siga estes passos:

  1. Vá para Email Testing e clique na caixa de entrada desejada.
  2. Clique em Show Credentials.
  3. Copie as credenciais em SMTP e cole-as no seu script PHPMailer ou na configuração do transporte SymfonyMailer.
  4. Alternativamente, escolha o pacote ou framework que você está usando no menu dropdown em Integrations e copie uma configuração de exemplo com suas credenciais.

Para o PHPMailer, a configuração do Email Testing ficará assim:

$phpmailer = new PHPMailer();
$phpmailer->isSMTP();
$phpmailer->Host = 'sandbox.smtp.mailtrap.io';
$phpmailer->SMTPAuth = true;
$phpmailer->Port = 2525;
$phpmailer->Username = 'seu_username';
$phpmailer->Password = 'sua_senha';

No SymfonyMailer, você deve definir o valor MAILER_DSN para o seguinte:

MAILER_DSN=smtp://seuusername:suasenha@sandbox.smtp.mailtrap.io:2525

API

Como mencionado acima, você pode usar o cliente PHP oficial do Mailtrap para enviar emails para a caixa de entrada virtual do Email Testing. Para isso, você precisará modificar o bloco try catch, obter um token da API para a caixa de entrada e copiar o ID da caixa de entrada.

  1. Crie um token da API como fizemos para o Email API/SMTP. Em Email Testing, escolha a caixa de entrada desejada.
Criando um token da API para a caixa de entrada do Email Testing
  1. Vá para Email Testing e abra a caixa de entrada desejada. No URL, você encontrará o ID da caixa de entrada de sete dígitos.
Copiando o ID da caixa de entrada do Email Testing

Adicione seu token da API ao arquivo .env e o ID da caixa de entrada ao seguinte script:

<?php

use Mailtrap\Config;
use Mailtrap\EmailHeader\CategoryHeader;
use Mailtrap\EmailHeader\CustomVariableHeader;
use Mailtrap\Helper\ResponseHelper;
use Mailtrap\MailtrapClient;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Header\UnstructuredHeader;

require __DIR__ . '/vendor/autoload.php';

// seu token API daqui https://mailtrap.io/api-tokens
$apiKey = getenv('CHAVE_API_DO_MAILTRAP');
$mailtrap = new MailtrapClient(new Config($apiKey));

$email = (new Email())
    ->from(new Address('exemplo@seu-dominio-aqui.com', 'Mailtrap Test'))
    ->replyTo(new Address('reply@seu-dominio-aqui.com'))
    ->to(new Address('email@exemplo.com', 'Jon'))
    ->priority(Email::PRIORITY_HIGH)
    ->cc('mailtrapqa@example.com')
    ->addCc('staging@example.com')
    ->bcc('mailtrapdev@example.com')
    ->subject('Dicas para criar emails em HTML')
    ->text('Oi! Aprenda as melhores práticas para criar emails HTML e experimentar templates pré-feitos. O guia do Mailtrap Como Criar Emails em HTML está já no nosso blogue')
    ->html(
        '<html>
        <body>
        <p><br>Oi</br>
        Aprenda as melhores práticas para criar emails HTML e experimentar templates pré-feitos.</p>
        <p><a href="https://mailtrap.io/pt/blog/build-html-email/">Mailtrap\'s Guide on How to Build HTML Email</a> is live on our blog</p>
        <img src="cid:logo">
        </body>
    </html>'
    )
    ->embed(fopen('https://mailtrap.io/wp-content/uploads/2021/04/mailtrap-new-logo.svg', 'r'), 'logo', 'image/svg+xml')
    ;
   
    // Cabeçalhos
    $email->getHeaders()
    ->addTextHeader('X-Message-Source', 'domain.com')
    ->add(new UnstructuredHeader('X-Mailer', 'Mailtrap PHP Client')) // o mesmo que addTextHeader
    ;
   
    // Variáveis Personalizadas
    $email->getHeaders()
    ->add(new CustomVariableHeader('user_id', '45982'))
    ->add(new CustomVariableHeader('batch_id', 'PSJ-12'))
    ;
   
    // Categoria (deve ser apenas uma)
    $email->getHeaders()
    ->add(new CategoryHeader('Integration Test'))
    ;
   
try {
    $response = $mailtrap->sandbox()->emails()->send($email, 1000001); // Parâmetro obrigatório -> inbox_id

    var_dump(ResponseHelper::toArray($response)); // corpo (array)
} catch (Exception $e) {
    echo 'Exceção capturada: ',  $e->getMessage(), "\n";
}

Você pode usar a API do Email Testing do Mailtrap para automatizar testes e testar múltiplas sequências.

Depois de integrar o Email Testing ao seu projeto PHP ou aplicação web, envie seu primeiro email de teste. Em seguida, verifique sua pontuação de spam; visualize-o em dispositivos móveis, desktops ou tablets; verifique se as versões HTML e texto são iguais; ou examine o HTML para elementos não suportados.

Inspecionando um email na caixa de entrada do Mailtrap Email Testing

Fique de olho em nosso canal no YouTube, pois nosso tutorial detalhado sobre testes de emails em PHP será lançado em abril. Até lá, dê uma lida neste artigo.

Palavras finais

Enquanto eu cobri pacotes e frameworks populares para enviar emails HTML em PHP, não mencionei o WordPress, pois é um tópico completamente diferente. O meu colega Veljko escreveu um tutorial detalhado sobre envio de emails no WordPress há algum tempo. Lá, você encontrará uma seção sobre envio de emails HTML, que deve cobrir suas necessidades por enquanto.

Article by Ketevan Bostoganashvili Technical Content Writer @Mailtrap

I’m a Technical Content Writer with more than 5 years of experience and passion to cover software engineering topics. I mostly write about email infrastructure and create code-rich guides about sending and testing emails, but I also love writing about result-driven email marketing.