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.
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:
<?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:
| Problema | Por que acontece |
|---|---|
| Sem PHP no host | GitHub 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 some | O 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 headers | O $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 é guardado | Se 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.
- 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.
- 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.
Tire o formulário do PHP
Mantenha os nomes dos campos exatamente como estão. Só o action muda, mais dois inputs ocultos:
<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><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.php | Agora |
|---|---|
$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: $email | Automá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 escreveu | O honeypot _gotcha, a pontuação de spam, os limites de taxa e a validação de campos |
- Adicione seu domínio em Allowed domains.
_redirectsó funciona com uma URLhttps:num desses domínios. - Apague o
contact.phpdo 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.phpnão existe mais. Bots que enviam direto para ela recebem um404, o que está ótimo.
Confira se funciona
- Em Allowed domains do formulário, adicione o domínio do seu site, mais
localhostenquanto desenvolve. Deixe vazio para aceitar envios de qualquer lugar. - Envie o formulário na sua página publicada. Você cai no seu antigo
thanks.html. - Abra Submissions no painel. O novo envio está lá com todos os campos que você enviou.
- 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.
- Clique em Reply. O endereço do visitante está na linha To.
- 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 chamadoemailou 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
| Problema | O que fazer |
|---|---|
| O navegador cai na página de agradecimento do Ikiform em vez da sua | O _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 spam | O 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 PHP | Uma 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 chegou | Ele 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
Sim. O script antigo continua funcionando até você mudar o action do formulário, então você pode testar o novo endpoint numa cópia da página primeiro, depois trocar e apagar o script.
Sim. Aponte o action do formulário para um backend de formulários em vez de um script PHP. O backend recebe o envio e manda um e-mail para você, então o seu site pode ser HTML puro em qualquer host estático.
Os scripts costumam definir o header From com o endereço do visitante, mas o e-mail sai do servidor do seu host. Isso falha nas verificações de SPF e DMARC do domínio do visitante, então o Gmail e o Outlook o tratam como falsificado. Um backend de formulários envia do próprio domínio e coloca o visitante em Reply-To.
Não. O Ikiform armazena os nomes que você enviar. Mantenha o campo de e-mail com o nome email, email_address, your_email, reply_to, contact_email, ou adicione um campo _replyto, para que as respostas vão para o visitante.
Ele resolve a entregabilidade se você envia por um provedor com o seu domínio configurado para SPF e DKIM. Você ainda precisa de um host PHP, validação, filtro de spam e de um lugar para guardar as mensagens. É uma boa escolha se você já mantém código PHP.
Travou em algum passo ou quer um guia para o seu caso? Envie um e-mail para hello@ikiform.com.