Enviar formulário de contato com anexo em PHP
Recentemente precisei montar um formulário de contato em PHP com a possibilidade de enviar um arquivo anexado, e percebi que o PHP não suporta isso nativamente pela função mail(). Como eu não quis usar nenhuma biblioteca de terceiros pronta, vi que seria necessário alterar o header do e-mail e acrescentar nele o anexo.
Para alcançar esse resultado, primeiramente precisei alterar o meu formulário. Este abaixo serve como exemplo, note o atributo enctype="multipart/form-data"
, sem ele não vai funcionar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!-- form.php --> <form action="envio.php" method="post" enctype="multipart/form-data"> <p> <label for="nome">Nome</label> <input type="text" name="nome" id="nome" required="" /> </p> <p> <label for="email">Email</label> <input type="email" name="email" id="email" required="" /> </p> <p> <label for="anexo">Anexo</label> <input type="hidden" name="MAX_FILE_SIZE" value="100000" /> <input type="file" id="anexo" name='anexo' /> </p> </form> |
No script que vai receber os dados para envio, verifico a existência do anexo, já que ele é opcional, e codifico ele no header do e-mail. Aproveito e também dou uma limpada nos textos enviados, para evitar o chamado Email injection, já que não devemos confiar em textos enviados pelo usuário.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php // evitar email injection function clean_string($string) { $bad = array( "content-type", "bcc:", "to:", "cc:", "href" ); return str_replace($bad, "", $string); } //variáveis $status = false; $nome = clean_string($_POST['nome']); $email = clean_string($_POST['email']); $mensagem = "Enviado pelo <strong>formulário de contato</strong>"; $assunto = "Contato"; // Assunto do E-mail // se o nome temporário do arquivo estiver vazio, ele não foi enviado if (empty($_FILES['anexo']['tmp_name'])) { //cabeçalho $headers = "Content-type: text/html; charset=utf-8\r\n"; $headers .= "From: $nome <$email>\r\n"; //E-Mail do destinatário $headers .= "Reply-To: $email\r\n"; //envio $status = mail ($destino, $assunto, $observacao, $headers); } else { // inicialmente, abre o arquivo e converte ele para base64 $file = $_FILES['anexo']['tmp_name']; $originalFile = $_FILES['anexo']['name']; $file_size = filesize($file); $handle = fopen($file, "rb"); $content = fread($handle, $file_size); fclose($handle); $content = chunk_split(base64_encode($content)); // separador aleatório necessário para enviar conteúdo mixed $separator = md5(time()); // fim de linha (usando uma constante do PHP para fim de linha) $eol = PHP_EOL; // cabeçalho principal (multipart obrigatório) $headers = "From: $nome <$email>" . $eol; $headers .= "MIME-Version: 1.0" . $eol; $headers .= "Content-Type: multipart/mixed; boundary=\"" . $separator . "\"" . $eol . $eol; $headers .= "Content-Transfer-Encoding: 8bit" . $eol; $headers .= "This is a MIME encoded message." . $eol . $eol; // mensagem (apenas formato html aqui) $headers .= "--" . $separator . $eol; $headers .= "Content-Type: text/html; charset=\"utf-8\"" . $eol; $headers .= $mensagem . $eol . $eol; // anexo usando o nome do arquivo original $headers .= "--" . $separator . $eol; $headers .= "Content-Type: application/octet-stream; name=\"" . $originalFile . "\"" . $eol; $headers .= "Content-Transfer-Encoding: base64" . $eol; $headers .= "Content-Disposition: attachment" . $eol . $eol; $headers .= $content . $eol . $eol; $headers .= "--" . $separator . "--"; // enviar email $status = mail($destino, $assunto, "", $headers); } if ($status) { echo "Envio com sucesso"; } else { echo "Ocorreu um erro no envio"; } |
Pronto, com isso agora o formulário é capaz de enviar os anexos corretamente.
Fontes