Receber um formulário no e-mail

Receber um formulário no e-mail6 min de leitura

Envie um formulário HTML para o e-mail sem PHP

Substitua um script contact.php que chama mail() por um formulário que envia a um endpoint hospedado, mantendo seus nomes de campo, sua página de agradecimento e as respostas.

Preet SutharFundador, Ikiform

Troque o action do formulário do seu script PHP pela URL de um backend de formulários, mantenha os nomes dos campos e apague o script. O backend faz o que o mail() fazia, mais as partes que ele nunca fez bem: filtro de spam, armazenamento e e-mails que não caem no spam. Funciona em hosts estáticos, onde o PHP nem roda.

O que muda aqui

A maioria dos formulários de contato em PHP são as mesmas vinte linhas, copiadas de um tutorial anos atrás. Eles leem $_POST, montam uma string, chamam mail() e redirecionam. Este é um exemplo típico:

contact.php
<?php
$name = $_POST["name"];
$email = $_POST["email"];
$phone = $_POST["phone"];
$message = $_POST["message"];

$to = "hello@example.com";
$subject = "Website enquiry from $name";
$body = "Name: $name\nEmail: $email\nPhone: $phone\n\n$message";
$headers = "From: $email\r\nReply-To: $email";

if (mail($to, $subject, $body, $headers)) {
  header("Location: /thanks.html");
} else {
  echo "Sorry, something went wrong.";
}

Parece inofensivo, e funcionava quando foi escrito. Hoje ele quebra de quatro formas, e só a primeira é óbvia:

ProblemaPor que acontece
Sem PHP no hostGitHub Pages, Netlify, Vercel, Cloudflare Pages e S3 servem arquivos; eles não rodam PHP. O formulário envia para um arquivo que nunca é executado, e você recebe um 404 ou 405.
O e-mail cai no spam ou someO mail() entrega a mensagem ao programa de e-mail local do servidor. O header From: diz ser o endereço do visitante, mas o e-mail sai do servidor do seu host, então falha nas verificações de SPF e DMARC do domínio do visitante. O Gmail e o Outlook filtram ou rejeitam, muitas vezes sem avisar.
Injeção de headersO $email entra nos headers sem verificação. Um bot que envia um valor com quebra de linha pode adicionar a própria linha Bcc: e usar seu formulário para mandar spam, o que coloca o IP do seu host em listas de bloqueio.
Nada é guardadoSe o e-mail se perde, a mensagem se perde junto. Não há registro, nem filtro de spam, nem como rever os contatos do mês passado.

Você poderia corrigir cada um: validar todos os valores, enviar por um provedor SMTP com uma biblioteca como o PHPMailer, configurar SPF e DKIM para o seu domínio, adicionar um honeypot e um limite de taxa e registrar tudo num banco de dados. É um projeto razoável se você já roda PHP. Se preferir não fazer isso, passe o trabalho para um backend de formulários.

O mesmo formulário com mail() do PHP e com um backend de formulárioscom contact.phpcom um backend de formuláriosseu formulárioaction="/contact.php"mail()From: o visitante,enviado pelo seuhostpasta de spamfalha no SPF eDMARCseu formuláriomesmos campos, novoactionIkiformfiltra spam,armazenasua caixa deentradaReply-To: ovisitanteenvioe-mail localenvioe-mailO mesmo formulário com mail() do PHP e com um backend de formulárioscom contact.phpcom um backend de formuláriosseu formulárioaction="/contact.php"mail()From: o visitante, enviado peloseu hostpasta de spamfalha no SPF e DMARCseu formuláriomesmos campos, novo actionIkiformfiltra spam, armazenasua caixa de entradaReply-To: o visitanteenvioe-mail localenvioe-mail
  1. Com o contact.php, o formulário envia ao seu host, e o mail() envia uma mensagem que diz vir do visitante. Os servidores de destino veem um remetente que não bate com o domínio e o jogam no spam ou o descartam.
  2. Com um backend de formulários, o formulário envia os mesmos campos ao Ikiform. O Ikiform envia o e-mail do próprio domínio e coloca o endereço do visitante em Reply-To, que é para isso que o Reply-To serve.
A solução para a entregabilidade não é um script melhor. É enviar de um domínio que tem permissão para enviar.

Tire o formulário do PHP

Mantenha os nomes dos campos exatamente como estão. Só o action muda, mais dois inputs ocultos:

Antes
<form action="/contact.php" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>
Depois
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <input type="hidden" name="_redirect" value="https://example.com/thanks.html" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>

Depois relacione cada coisa que o script fazia com o lugar onde ela fica agora:

No contact.phpAgora
$to = "hello@example.com"Destinatários nas configurações de Notifications do formulário
header("Location: /thanks.html")O input oculto _redirect, ou Redirect after submit nas configurações do formulário
Reply-To: $emailAutomático, porque o campo se chama email
$subject = "Website enquiry from $name"Fixo como New submission: <form name>. Dê ao formulário o nome "Contato pelo site" para manter o texto
echo "Sorry, something went wrong."A página de erro do Ikiform para um envio simples, ou sua própria mensagem com fetch
Verificações que você nunca escreveuO honeypot _gotcha, a pontuação de spam, os limites de taxa e a validação de campos
  • Adicione seu domínio em Allowed domains. _redirect só funciona com uma URL https: num desses domínios.
  • Apague o contact.php do servidor quando o novo formulário estiver funcionando. Um script esquecido continua sendo um relay de e-mail aberto para bots que lembram a URL.
  • Se você migrou para um host estático, a antiga URL /contact.php não existe mais. Bots que enviam direto para ela recebem um 404, o que está ótimo.
Se o seu formulário era um plugin do WordPress em vez de um script, a mesma ideia vale. O guia do WordPress mostra onde colocar o formulário num tema de blocos.

Confira se funciona

  1. Em Allowed domains do formulário, adicione o domínio do seu site, mais localhost enquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar.
  2. Envie o formulário na sua página publicada. Você cai no seu antigo thanks.html.
  3. Abra Submissions no painel. O novo envio está lá com todos os campos que você enviou.
  4. Abra o e-mail. Ele vem do Ikiform, não do endereço do visitante, e não está no spam. Adicione o remetente aos seus contatos para que os próximos também não caiam.
  5. Clique em Reply. O endereço do visitante está na linha To.
  6. Envie com o honeypot preenchido, _gotcha=bot. Ele ainda recebe uma resposta de sucesso, mas o envio é armazenado como spam e não dispara e-mail nem webhook.

Pegadinhas

  • Nomes antigos com colchetes. Formulários PHP muitas vezes usam nomes como contact[email]. O Ikiform os armazena como estão, mas o reply-to só vem de um campo chamado email ou de algumas variações próximas. Renomeie o campo ou adicione _replyto.
  • O assunto não pode incluir o nome. O assunto do script tinha o nome do visitante. O assunto da notificação é fixo, e _subject é repassado aos webhooks e à API sem mudar o e-mail.
  • Codificação de caracteres. Scripts com mail() muitas vezes estragavam os acentos porque nunca definiam um charset. O e-mail do Ikiform é UTF-8, então nomes em qualquer alfabeto chegam intactos.
  • Vários endereços em $to. Uma lista separada por vírgulas no script vira destinatários separados no painel. Endereços de fora confirmam por link antes de receber qualquer coisa. Veja vários destinatários.

Se algo der errado

ProblemaO que fazer
O navegador cai na página de agradecimento do Ikiform em vez da suaO _redirect é ignorado, a menos que o domínio dele esteja em Allowed domains e ele seja uma URL https:. Adicione o domínio, ou defina Redirect after submit nas configurações do formulário.
403 origin_not_allowed, ou todo envio cai no spamO domínio da página não está em Allowed domains do formulário. Adicione-o, mais localhost para testes locais. Subdomínios de um domínio listado são permitidos.
O formulário ainda envia para o arquivo PHPUma página em cache ou uma segunda cópia do formulário, como um include no rodapé, ainda tem o action antigo. Procure contact.php no site.
O envio está no painel, mas nenhum e-mail ou webhook chegouEle foi armazenado como spam. Spam não envia nada. Abra-o no filtro Spam para ver os motivos e marque-o como não spam para enviar o e-mail e os webhooks dele.

Perguntas

Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.