Um formulário de contato não deve confiar apenas na função mail() nem colocar o endereço digitado pelo visitante no cabeçalho From. A abordagem mais confiável usa uma biblioteca mantida, SMTP autenticado, validação dos campos, proteção contra automação e registros DNS de entregabilidade.
Arquitetura recomendada
- O navegador envia os dados por HTTPS para seu backend.
- O backend valida tamanho, formato e conteúdo.
- Uma proteção contra spam limita abuso.
- A aplicação autentica em uma conta SMTP do seu domínio.
- O campo
Fromusa essa conta; o e-mail do visitante vai emReply-To. - Erros são registrados sem salvar senha nem conteúdo sensível desnecessário.
Prepare a conta de envio
No cPanel, crie uma conta específica, como site@seudominio.com.br. Em Email Accounts > Connect Devices, copie servidor SMTP, porta e criptografia. Use uma senha exclusiva e guarde-a em variável de ambiente ou cofre de segredos, fora do repositório.
Instale o PHPMailer
composer require phpmailer/phpmailer
O Composer deve ser executado no ambiente de desenvolvimento ou no fluxo de implantação. Não exponha o diretório vendor para download e mantenha dependências atualizadas.
Exemplo seguro de envio
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require __DIR__ . '/vendor/autoload.php';
$name = trim((string) ($_POST['name'] ?? ''));
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
$message = trim((string) ($_POST['message'] ?? ''));
if ($name === '' || !$email || $message === '' ||
mb_strlen($name) > 120 || mb_strlen($message) > 5000) {
http_response_code(422);
exit('Revise os campos informados.');
}
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = getenv('SMTP_HOST');
$mail->SMTPAuth = true;
$mail->Username = getenv('SMTP_USER');
$mail->Password = getenv('SMTP_PASS');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
$mail->CharSet = 'UTF-8';
$mail->setFrom(getenv('SMTP_USER'), 'Site da empresa');
$mail->addAddress('atendimento@seudominio.com.br');
$mail->addReplyTo($email, $name);
$mail->Subject = 'Novo contato pelo site';
$mail->Body = "Nome: {$name}\nE-mail: {$email}\n\n{$message}";
$mail->send();
echo 'Mensagem enviada.';
} catch (Exception $exception) {
error_log('Falha no formulário: ' . $mail->ErrorInfo);
http_response_code(500);
echo 'Não foi possível enviar agora. Tente novamente.';
}
465 com SMTPS é um exemplo comum. Use exatamente porta, criptografia e hostname mostrados no cPanel. Para porta 587, a configuração normalmente usa STARTTLS.Proteja o formulário contra abuso
- token CSRF para requisições da própria sessão;
- campo “honeypot” invisível para bots simples;
- limite de requisições por IP e por sessão;
- CAPTCHA quando o risco justificar;
- limites de tamanho e lista explícita de campos;
- escape ao exibir qualquer conteúdo enviado;
- bloqueio de anexos ou validação rigorosa de tipo, conteúdo e tamanho;
- logs com retenção e proteção adequadas à privacidade.
SPF, DKIM e DMARC
Em Email Deliverability, verifique SPF e DKIM. O DMARC deve ser publicado de forma gradual e monitorada. Esses registros não corrigem um formulário vulnerável, mas ajudam servidores destinatários a validar o domínio. Se o DNS estiver na Cloudflare ou em outro provedor, publique os registros no DNS autoritativo, não apenas no cPanel.
Por que não usar o visitante como From
Se alguém informa pessoa@gmail.com e o seu servidor envia como se fosse o Gmail, SPF e DMARC podem falhar. Use uma conta do seu domínio no From e o endereço validado do visitante em Reply-To. Também remova quebras de linha e limite campos para evitar injeção de cabeçalhos.
Diagnóstico
- Authentication failed: revise usuário completo, senha e autenticação SMTP.
- Connection timed out: revise host, porta, firewall e se o provedor permite saída nessa porta.
- TLS/certificate error: use o hostname seguro indicado pelo serviço; não desative validação do certificado.
- Envia, mas cai no spam: confira conteúdo, reputação, SPF, DKIM, DMARC e se o destinatário marcou mensagens anteriores.
- Limite excedido: não use hospedagem comum para disparos em massa; adote um serviço transacional apropriado.
Checklist antes de publicar
- HTTPS ativo;
- senha fora do código e do Git;
- From pertencente ao domínio autenticado;
- Reply-To validado;
- CSRF, rate limit e antispam ativos;
- mensagem de erro não revela detalhes internos;
- teste em Gmail, Outlook e outro domínio;
- política de privacidade informa o tratamento dos dados.
Novos guias relacionados
Aprofunde o diagnóstico com estes conteúdos atualizados:
- Erro 550 5.7.1 Message Rejected ou Detected as Spam: como identificar e corrigir
- Erro SMTP 535 5.7.8 Authentication Failed: senha, usuário, porta e bloqueio
- Erro Sender Verify Failed, Invalid Sender ou 550 5.1.7: remetente rejeitado
- E-mail enviado cai no Spam ou lixo eletrônico: diagnóstico completo de entregabilidade
Recursos relacionados
Continue com materiais e serviços relacionados ao tema deste guia.