Enviando e-mail com AJAX e PHP via protocolo SMTP
Esse tutorial tem como objetivo principal descrever o funcionamento básico de um sistema de envio de e-mails utilizando AJAX com PHP e autenticação via protocolo SMTP.
No passado muitos servidores aceitavam o envio de e-mails sem autenticação. Esse excesso de privilégios possibitava utilizar esses servidores para a prática de SPAM. Atualmente as boas práticas de segurança sugerem que toda comunicação através de e-mail deve utilizar autenticação SMTP, mesmo que para simplesmente enviar formulários HTML.
Para trabalhar com SMTP via PHP vamos utilizar uma classe chamada PHPMailer.
As funções javascript serão escritas utilizando jQuery.
Caminho lógico da mensagem:
1) Uma função javascript coleta os dados de um formulário HTML e alimenta um cliente ajax.
2) O ajax envia ao servidor PHP as informações coletadas no passo anterior e aguarda o retorno.
3) Enquanto isso o servidor PHP coleta as informações e faz login no servidor SMTP, solicitando um disparo de e-mail.
4) Se tudo estiver ‘ok’ o servidor SMTP dispara o e-mail e envia uma mensagem de retorno para o servidor PHP.
5) O servidor PHP devolve o retorno para o cliente ajax.
6) O cliente ajax imprime o resultado da requisição no HTML.
Com esse conjunto temos um método completo para disparo de e-mails autenticados sem recarregar a página do cliente!
Enviando e-mail com AJAX e PHP via protocolo SMTP
1.0 – HTML
1.0 – HTML
Tudo começa no formulário HTML, resolvi adotar a propriedade “id” para fazer referência no javascript, mas você pode utilizar qualquer outro seletor. Note que há um id para cada componente assim como há para a div. O retorno da requisição ajax irá modificar o conteúdo dessa div, imprimindo o resultado gerado pelo envio do e-mail.
Há também uma imagem que pertence a classe “loading”. Essa imagem será utilizada para fazer a animação tipo “carregando” que é exibida enquanto o ajax aguarda o retorno. Para gerar imagens personalizadas tipo “loading” acesse ajaxload.info.
<div id="retornoHTML"> <form> Nome<br> <input id="nome" type="text"><br> E-mail<br> <input id="email" type="text"><br> Mensagem:<br> <textarea id="msg"></textarea><br> <input type="button" id="btn" value="ENVIAR"> <img src="loading.gif" class="loading"> </form> </div>
1.1 – jQuery, coletando dados.
Vamos utilizar uma função javascript para coletar os dados do formulário desenvolvido no passo anterior.
$('#btn').click( function(){ /* Quando clicar em #btn */ var nome = $('#nome').val(); var email = $('#email').val(); var msg = $('#msg').val(); });
1.2 – Montando URL.
Devemos montar uma url com os dados coletados para serem enviados ao PHP via Ajax:
/* construindo url */ var urlData = "&nome=" + nome + "&email=" + email + "&msg=" + msg;
2.0 Ajax – Enviando dados para o PHP via POST.
/* Ajax */ $.ajax({ type: "POST", /* tipo post */ url: "sendmail.php", /* endereço do script PHP */ async: true, data: urlData, /* informa Url */ success: function(data) { /* sucesso */ /* alert(data) */ /* pode ser utilizado um alert para ver o retorno */ $('#retornoHTML').html(data); /* imprime o retorno no HTML */ }, beforeSend: function() { /* antes de enviar */ $('.loading').fadeIn('fast'); /* mostra o loading */ }, complete: function(){ /* completo */ $('.loading').fadeOut('fast'); /* esconde o loading */ } });
2.1 – Validando informações
O ideal seria utilizar alguma validação para não enviar valores nulos ou inválidos pois o PHPMailer pode retornar erro. Recomendo utilizar um validador próprio para o campo de e-mail, este script não trata esse tipo de problema. Abaixo um exemplo simples de validação:
/* Validando */ if(nome.length <= 3){ alert('Informe seu nome'); return false; } if(email.length <= 5){ alert('Informe seu email'); return false; } if(msg.length <= 5){ alert('Escreva uma mensagem'); return false; }
Javascript Completo:
$(document).ready( function(){ //Quando documento estiver pronto $('#btn').click( function(){ /* Quando clicar em #btn */ /* Coletando dados */ var nome = $('#nome').val(); var email = $('#email').val(); var msg = $('#msg').val(); /* Validando */ if(nome.length <= 3){ alert('Informe seu nome'); return false; } if(email.length <= 5){ alert('Informe seu email'); return false; } if(msg.length <= 5){ alert('Escreva uma mensagem'); return false; } /* construindo url */ var urlData = "&nome=" + nome + "&email=" + email + "&msg=" + msg ; /* Ajax */ $.ajax({ type: "POST", url: "sendmail.php", /* endereço do script PHP */ async: true, data: urlData, /* informa Url */ success: function(data) { /* sucesso */ $('#retornoHTML').html(data); }, beforeSend: function() { /* antes de enviar */ $('.loading').fadeIn('fast'); }, complete: function(){ /* completo */ $('.loading').fadeOut('fast'); //wow! } }); }); });
3.0 – PHP, coletando dados, configurando mensagem e disparando e-mail
Nos passos anteriores construímos o formulário HTML, copiamos o conteúdo utilizando jQuery e criamos um cliente ajax, que utilizando método POST, aponta um endereço de url (var urlData) para o script “sendmail.php”.
O código a seguir ilustra o conteúdo desse script, coleta as informações e gera o e-mail (html) que será enviado. O conteúdo do e-mail enviado pode ser gerado no próprio script, ou adicionado através de qualquer método que a linguagem comporte.
A primeira linha aponta para a classe PHPMailer. Faça download aqui e caso necessário troque o caminho do arquivo.
require_once('PHPMailer_5.2.1/class.phpmailer.php'); /* classe PHPMailer */ /* Recebe os dados do cliente ajax via POST */ $nome = $_POST['nome']; $email = $_POST['email']; $msg = $_POST['msg']; try { $mail = new PHPMailer(true); //New instance, with exceptions enabled /* CORPO DO E-MAIL */ $body .= "<h2>Enviando e-mails com AJAX e PHP via SMTP</h2>"; $body .= "Nome: $nome <br>"; $body .= "E-mail: $email <br>"; $body .= "Mensagem:<br>"; $body .= $msg; $body .= "<br>"; $body .= "----------------------------"; $body .= "<br>"; $body .= "Enviado em <strong>".date("h:m:i d/m/Y")." por ".$_SERVER['REMOTE_ADDR']."</strong>"; //mostra a data e o IP $body .= "<br>"; $body .= "----------------------------"; $mail->IsSMTP(); //tell the class to use SMTP $mail->SMTPAuth = true; // enable SMTP authentication $mail->Port = 587; //SMTP porta (as mais utilizadas são '25' e '587' $mail->Host = "smtp.meudominio.com"; // SMTP servidor $mail->Username = "contato@meudominio.com"; // SMTP usuário $mail->Password = "senha123abc"; // SMTP senha $mail->IsSendmail(); $mail->AddReplyTo($email, $nome); //Responder para.. $mail->From = $email; //e-mail fornecido pelo cliente $mail->FromName = $nome; //nome fornecido pelo cliente $to = "meuemail@meuservidor.com"; //Enviar para $mail->AddAddress($to); $mail->Subject = "Assunto do E-mail"; //Assunto $mail->WordWrap = 80; // set word wrap $mail->MsgHTML($body); $mail->IsHTML(true); // send as HTML $mail->Send(); echo 'Mensagem enviada com sucesso.'; //retorno devolvido para o ajax caso sucesso } catch (phpmailerException $e) { echo $e->errorMessage(); //retorno devolvido para o ajax caso erro }
O script utilizado neste exemplo é encontrado entre os modelos do pacote PHPMailer.
IMPORTANTE: Você deve conferir junto ao seu provedor de e-mails quais são os endereços SMTP, senha e qual a porta pra envio de e-mails autenticados.
4.0 – CSS!
Lembre-se que a imagem “loading” não deve estar visível quando carregar o site. Adicione a classe no CSS:
.loading { display: none; }
Download
Você pode fazer o download de todos os arquivos utilizados nesse tutorial, clique aqui.
Que legal cara, fiz o passo-a-passo e funcionou, antes tinha tentado outro mas esse é muito mais fácil. Valeu!
ótimo passo-a-passo, funcionou.
Maravilha o tutorial, muito bom.
Boa noite!
O script realmente é ótimo, no entanto gostaria de deixar alguns complementos para solução de alguns problemas que tive ao reproduzir o script!
1 – quem estiver utilizando o WampServer deverá habilitar a extensão do php chamada php_openssl, para habilitar a segurança ssl/tsl.
2 – excluir ou desabilitar a linha 34 do código php – #$mail->IsSendmail(); pois o Wanp não tem o IsSendMail.
3 – deverá adicionar abaixo da variável “$mail->SMTPAuth = true; // enable SMTP authentication” – a variável $mail->SMTPSecure = “tls”;
4 – A porta pra quem utilizar o hotmail como servidor é 587 e não 25.
Pra quem teve problemas , depois de efetuar estas alterações aparecer a mensagem de que não foi possivel autenticar, verificar se tem em sua senha caracteres especiais como $%* e etc…
ai é só alterar a senha ou usar os escapes do PHP, como exemplo colocando a “barra invertida” antes do caractere especial, exe.: alan* – troco por alan\*
Valew galera até mais!!!!
puxa… não consegui…
A dúvida maior é onde colocar essa classe do require_once e se todo o código fica em uma única página ou páginas distintas… eu nunca consegui fazer um exemplo com ajax que tenha tido sucesso… 🙁
cara, nem testei ainda mas ta de parabéns hein. acho que foi o tutorial mais bem explicado do assunto que encontrei.
muchas gracias, me fue bastante util! Muito obrigado!
Não funcionou preciso de ajuda, fiz tudo conforme mas não funcionou.
Cara, passei aqui pra dar um salve porque seu post me ajudou bastante na resolução de um problema. Precisei de algumas modificações mas no geral foi muito esclarecedor.
Parabéns.
Muito obrigado mesmo pela colaboração:
1 – da explicação bem feita
2 – do script pronto sem complicações.
Continue assim, valeu mesmo pela ajuda.
Onde coloco o email para onde a mensagem será enviada?
Segui passo a passo o tutorial, e quando executei apareceu o seguinte erro: ‘Notice: Undefined index: nome in C:\wamp\www\Teste2\js\php\sendMail.php on line 6’, em todas as variáveis criadas em php. Poderia me ajudar?
Muito bom cara, foi muito útil. Abraço!
Gostaria de montar um site em php, vale a pena?
Sim, vale.
Show de bola. Apesar de ser antigo, ainda é muito funcional. Gostaria de saber se tem como implementar o recaptcha do google nesse script e se alguém que conseguiu, poderia dar uma explanação?
Opa, bastante funcional o seu tutorial, rodou muito bem em um trampo que fiz.
Tenho uma duvida, implementei no site de um cliente com um formulário já personalizado que eu já tinha criado, mas quando o email chega na caixa de entrada não interpreta o fica tudo em uma linha só, não consegui entender. Grato desde já