En este HowTo aprenderás a crear y construir un formulario de contacto responsive desde cero, usando diferentes tecnologías y técnicas web.
Antes de empezar a crear el formulario de contacto vamos a hacer un resumen de las diferentes tecnologías y técnicas web que vamos a necesitar.
- Lenguaje de marcado HTML5.
- CSS + frameworks Bootstrap 4.1 y FontAwesome 5 para maquetar y estilar el formulario.
- JavaScript y AJAX para enviar el formulario de forma asíncrona.
- PHP 7> para recepcionar los datos y PHPMailer 5> Stable para realizar el envío del email.
- JSON para intercambiar los datos de PHP a JavaScript.
- Google reCaptcha para evitar spam del formulario.
Creando el formulario HTML
Vamos a empezar creando el fichero que contendrá nuestro formulario. Para ello primeramente crearemos la cabecera del documento que contendrá todos nuestros scripts, frameworks, etc ..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!doctype <!DOCTYPE html> <html lang="es"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Contact Form</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- bootstrap 4> --> <link rel="stylesheet" type="text/css" href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" /> <!-- font awesome 5> --> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> <!-- my styles--> <link rel="stylesheet" href="assets/css/style.css" /> <!-- my scripts --> <script type="text/javascript" src="assets/js/contacto.js"></script> </head> <body> |
A continuación ya podremos incluir el formulario creado con Bootstrap 4>
- Se compone de 4 campos (nombre, teléfono, email, observaciones), el botón de envío y un área donde mostraremos los mensajes de respuesta (errores, etc …)
- Para la validación de los campos no vamos a complicarnos y usaremos la atributo required de HTML5
- La llamada a google reCAPTCHA donde incluiremos la clave pública.
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 |
<div class="container"> <h1>Contact Form</h1> <p>Contact form made with HTML5, ECMAScript+Ajax, PHP+PHPMailer 5.2, CSS+Bootstrap, JSON</p> <div class="alert" id="messages"></div> <form method="post" action="" name="contact" id="contact" onsubmit="enviar(this); return false;"> <hr /> <!-- nombre --> <div class="form-group"> <label for="name">Nombre/Apellidos:</label> <div class="input-group"> <div class="input-group-prepend"> <div class="input-group-text"><i class="fas fa-user"></i></div> </div> <input type="text" class="form-control" placeholder="Nombre" id="name" name="name" required /> </div> </div> <!-- telefono --> <div class="form-group"> <label for="phone">Teléfono</label> <div class="input-group"> <div class="input-group-prepend"> <div class="input-group-text"><i class="fas fa-mobile-alt"></i></div> </div> <input type="text" class="form-control" id="phone" name="phone" placeholder="Teléfono" required /> </div> </div> <!-- email --> <div class="form-group"> <label>Email:</label> <div class="input-group"> <div class="input-group-prepend"> <div class="input-group-text"><i class="fas fa-envelope"></i></div> </div> <input type="email" class="form-control" id="email" name="email" placeholder="su@email" required /> </div> <small id="emailHelp" class="form-text text-muted">Su email no será compartido con nadie.</small> </div> <!-- mensaje --> <div class="form-group"> <label for="subject">Asunto:</label> <textarea placeholder="Asunto" id="subject" name="subject" class="form-control" required></textarea> </div> <!-- google recaptcha --> <script src='https://www.google.com/recaptcha/api.js'></script> <div class="g-recaptcha" data-sitekey="your-public-site-recaptcha-key"></div> <hr /> <!-- submit --> <button type="submit" id="send" name="send">Enviar</button> </form> </div> </body> </html> |
JavaScript y AJAX
Por supuesto el formulario no funcionará sin JavaScript y Ajax.
- La función enviar() se encarga de enviar el formulario de contacto usando AJAX usando el objeto formData que nos permite recopilar los datos del formulario para luego poder transmitirlos usando el objeto XMLHttpRequest
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 |
function enviar() { var messagesElement = document.getElementById("messages"); // disable send button document.querySelector("#send").disabled = true; document.querySelector("#send").innerText = "Enviando ..."; // show messages document.querySelector("#messages").style.display = "block"; // XHR object var xhr = new XMLHttpRequest(); xhr.onload = function(res) { if (xhr.status == 200) { console.log("resultado:"+xhr.status); var res = JSON.parse(this.response); document.querySelector("#messages").innerHTML = res.message; //document.querySelector("#messages").innerHTML += res.msg_phpmailer; console.log(xhr.responseText); if (res.error == false) { document.querySelector("#contact").style.display = "none"; document.querySelector("#messages").classList.remove("alert-danger"); document.querySelector("#messages").classList.add("alert-success"); document.querySelector("#messages").innerHTML = res.message; } else { document.querySelector("#messages").classList.add("alert-danger"); document.querySelector("#send").disabled = false; document.querySelector("#send").innerText = "Reintentar el envío"; } } else { // log error document.querySelector("#send").disabled = false; document.querySelector("#messages").innerHTML = "Se ha producido un error, contacte con el administrador"; console.log("error"+xhr.status); } } // preapare request var formMethod = "POST"; var formUrl = 'mod/enviar.php'; var formType = true; xhr.open(formMethod, formUrl, formType); // prepare form data var formElement = document.getElementById("contact"); var data = new FormData(formElement); xhr.send(data); } |
Recepción y envío del formulario
Una vez que Ajax se comunica con el fichero PHP que le hallamos indicado, este empezará la transmisión de los datos al fichero enviar.php. Vamos a ver con detalle el contenido de este:
- Lo primero que hacemos es comprobar el CAPTCHA introducido por el usuario. Es importante que lo tengamos bien configurado y que la clave pública coincida con la clave secreta.
- Recepcionamos los datos del formulario y los validamos usando la función filter_input() de PHP
- Una vez hecho esto ya podemos realizar una llamada a la clase PHPMailer donde configuramos la cuenta de correo que enviará los correos, la cuenta de destino y otros parámetros que necesitemos.
- Sino se detectamos ningún error enviamos el correo.
- Devolvemos los datos en formato JSON y que creemos necesarios para que los interprete JavaScript y así avisar al usuario si el envío ha sido satisfactorio o los errores que han sido encontrados.
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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
<?php header("Content-Type: application/json"); // catcha google $recaptcha = 1; $error = false; // google recaptcha v2.0 $secretkey = "tu-secret-key-de-google-recaptcha"; $captcha=$_POST['g-recaptcha-response']; $ip = $_SERVER['REMOTE_ADDR']; $response=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secretkey."&response=".$captcha."&remoteip=".$ip); $responseKeys = json_decode($response,true); // check response if(intval($responseKeys["success"]) !== 1) { $recaptcha = 0; } // get post values $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING); $phone = filter_input(INPUT_POST, 'phone', FILTER_SANITIZE_STRING); $email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL); $subject = filter_input(INPUT_POST, 'subject', FILTER_SANITIZE_STRING); // email template include_once "template.php"; // sending email include_once '../includes/classes/PHPMailer-5.2-stable/PHPMailerAutoload.php'; // PHPMailer instance $mail = new PHPMailer; //Tell PHPMailer to use SMTP $mail->isSMTP(); $mail->CharSet = 'UTF-8'; //Enable SMTP debugging // 0 = off (for production use) // 1 = client messages // 2 = client and server messages $mail->SMTPDebug = 0; //Ask for HTML-friendly debug output $mail->Debugoutput = 'html'; //Set the hostname of the mail server $mail->Host = "mail.dominio.com"; //Set the SMTP port number - likely to be 25, 465 or 587 $mail->Port = 587; //Set the encryption system to use - ssl (deprecated) or tls //$mail->SMTPSecure = 'tls'; // gmail $mail->SMTPAutoTLS = false; //Whether to use SMTP authentication $mail->SMTPAuth = true; //Username to use for SMTP authentication $mail->Username = "tu@correo"; //Password to use for SMTP authentication $mail->Password = "tuclave"; //Set who the message is to be sent from $mail->setFrom('tu@correo', 'jose'); //Set an alternative reply-to address $mail->addReplyTo('tu@correo', 'jose'); //Set who the message is to be sent to $mail->addAddress('destino@dominio.com', 'jose'); //Set the subject line $mail->Subject = "Formulario de contacto enviado desde artegrafico.net"; //Read an HTML message body from an external file, convert referenced images to embedded, //convert HTML into a basic plain-text alternative body //$mail->msgHTML(file_get_contents('template.html'), dirname(__FILE__)); $mail->msgHTML($template); //Replace the plain text body with one created manually //$mail->AltBody = 'This is a plain-text message body'; //Attach an image file //$mail->addAttachment('images/phpmailer_mini.png'); if ($recaptcha == 1) { if (!$mail->send()) { $error = true; $message = "El formulario de contacto no se pudo enviar, contacte con el administrador."; $msg_phpmailer = $mail->ErrorInfo; } else { $message = "Gracias por contactar con nosotros!<br />Le responderemos en la mayor brevedad posible."; } } else { // captcha error $error = true; $message = "Error: Revise el captcha."; } // return response echo json_encode([ 'debug' => 'nombre: '.$name.'<br />phone: '.$phone.'<br />email: '.$email.'<br />subject: '.$subject, 'error' => $error, 'message' => $message, 'error_phpmailer' => $error_phpmailer ]); |