Envío de formularios web por email con PHP y jQuery AJAX

Hace algún tiempo publique una entrada para crear un formulario multi pasos con html, jquery y css3. Pero nunca explique cómo enviar ese formulario y he recibido varias consultas preguntando eso, así que por fin le dedique un poco de tiempo y crearemos un sencillo script php para el envío de formularios web por email con PHP y jQuery AJAX.

Que necesitamos?

Un formulario (obvio) incluso podría usarse el formulario multipasos ya explicado en esta entrada, pero para fines practico crearemos uno mas simple, pero el método es aplicable a cualquier formulario.

  • Formulario HTML.
  • Un servidor web con php.

Nuestro formulario

<div class="form-style" id="contact_form">
<div class="form-style-heading">SuperMegaDuperHiper Formulario</div>
<div id="contact_body">
<label>
<span>Nombre <span class="required">*</span></span>
<input type="text" name="name" id="name" required="true" class="input-field"/>
</label>
<label>
<span>Email <span class="required">*</span></span>
<input type="email" name="email" required="true" class="input-field"/>
</label>
<label>
<span>Fono</span>
<input type="text" name="phone1" maxlength="4" placeholder="+91"  required="true" class="tel-number-field"/>&mdash;
<input type="text" name="phone2" maxlength="15"  required="true" class="tel-number-field long" />
</label>
<label for="subject">
<span>Asunto</span>
<select name="subject" class="select-field">
<option value="Felicitaciones">Felicitaciones</option>
<option value="Petición">Petici&oacute;n</option>
<option value="Reclamo">Reclamo</option>
</select>
</label>
<label for="field5">
<span>Mensaje <span class="required">*</span></span>
<textarea name="message" id="message" class="textarea-field" required="true"></textarea>
</label>
<label>
<span>&nbsp;</span>
<input type="submit" id="submit_btn" value="Submit" />
</label>
</div>
</div>

Los mas suspicaces notaran que no existe la etiqueta form y esto no es un error del todo, semanticamente no seria correcto si lo validamos con el w3c, pero lo podemos resolver eligiendo el doctype mas adecuado, en este caso html5, así que lo agregamos a nuestro documento html.

<!DOCTYPE html>

Bien y el resultado seria mas menos lo siguiente:

Mmmm, realmente es un formulario muy básico xD, pongamos un poco de color ayudados por css.

Creamos un nuevo documento con extensión .css yo lo llamare style.css (que original).

/* ajuste basico del documento */
body,html{background: #E0EFF1;margin: 0px;padding: 0px;}
/* estilos del formulario */
.form-style{
 max-width: 450px;
 padding: 40px 30px 40px 40px;
 font: 13px Arial, Helvetica, sans-serif;
 margin: 50px auto;
 background: #fff;
     border-radius: 5px;
 -webkit-border-radius:5px;
    -moz-border-radius:5px;
         box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.2);
 -webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.2);
}
.form-style-heading{
 font-weight: bold;
 font-style: italic;
 border-bottom: 2px solid #ddd;
 margin-bottom: 10px;
 font-size: 15px;
 padding-bottom: 3px;
}
.form-style label{display: block;margin: 0px 0px 15px 0px;}
.form-style label > span{
 width: 100px;
 font-weight: bold;
 float: left;
 padding-top: 8px;
 padding-right: 5px;
}
.form-style span.required{color:red;}
.form-style .tel-number-field{width: 40px;text-align: center;}
.form-style  .long{width: 120px;}
.form-style input.input-field{width: 48%;}

.form-style input.input-field,
.form-style .tel-number-field,
.form-style .textarea-field,
.form-style .select-field{
 -webkit-transition: all 0.30s ease-in-out;
    -moz-transition: all 0.30s ease-in-out;
     -ms-transition: all 0.30s ease-in-out;
      -o-transition: all 0.30s ease-in-out; 
         box-sizing: border-box;
 -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
 border: 1px solid #C2C2C2;
     box-shadow: 1px 1px 4px #EBEBEB;
    -moz-box-shadow: 1px 1px 4px #EBEBEB;
 -webkit-box-shadow: 1px 1px 4px #EBEBEB;
     border-radius: 3px;
 -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
 padding: 7px;
 outline: none;
}
.form-style .input-field:focus,
.form-style .tel-number-field:focus,
.form-style .textarea-field:focus,  
.form-style .select-field:focus{
 border: 1px solid #7DB4B5;
}
.form-style .textarea-field{height:100px;width: 55%;}
.form-style input[type="button"],
.form-style input[type="submit"] {
    -moz-box-shadow: inset 0px 1px 0px 0px #3985B1;
 -webkit-box-shadow: inset 0px 1px 0px 0px #3985B1;
     box-shadow: inset 0px 1px 0px 0px #3985B1;
 background-color: #216288;
 border: 1px solid #17445E;
 display: inline-block;
 cursor: pointer;
 color: #FFFFFF;
 padding: 8px 18px;
 text-decoration: none;
 font: 12px Arial, Helvetica, sans-serif;
}
.form-style input[type="button"]:hover,
.form-style input[type="submit"]:hover {
 background: linear-gradient(to bottom, #2D77A2 5%, #337DA8 100%);
 background-color: #28739E;
}
.form-style .success{
 background: #D8FFC0;
 padding: 5px 10px 5px 10px;
 margin: 0px 0px 5px 0px;
 border: none;
 font-weight: bold;
 color: #2E6800;
 border-left: 3px solid #2E6800;
}
.form-style .error {
 background: #FFE8E8;
 padding: 5px 10px 5px 10px;
 margin: 0px 0px 5px 0px;
 border: none;
 font-weight: bold;
 color: #FF0000;
 border-left: 3px solid #FF0000;
}

Ahora nuestro formulario si luce bien.

screenshot.1

Pero un momento, si el formulario no tiene la etiqueta

<form></form>

  como enviaremos el formulario sin el atributo action?. La respuesta es bien simple… Con Jquery Ajax por supuesto. Podemos crear un Archivo independiente para el script Jquery o integrarlo en la cabecera de nuestro documento html dentro de una etiqueta 

<script type="text/javascript">

  , yo lo incluiré dentro del documento.

Primero  declaramos un document ready

$(document).ready(function(){});

  y dentro programamos las validaciones básicas.

El código esta fuertemente comentado, por tanto no lo explicaré detalladamente (si existen dudas o incluso pueden aportar mejoras, comentarlas).

Debemos realizar las validaciones del lado del cliente antes que se envíe el formulario y presentar los errores si es que existen, para ello activamos nuestras validaciones con el método .click de jQuery, en términos mas simples, nuestro código jQuery se activara una vez realicemos un clic al botón enviar.

Usando los selectores de jQuery, vigilamos la acción .click()

$(document).ready(function(){
//usaremos el metodo .click() de jQuery para iniciar
//las validaciones del lado del cliente y enviar el formulario
$("#submit_btn").click(function(){
//creamos una variable como flag(bandera), 
//la usaremos para detener el script si no 
//se cumplen las reglas de validacion
var continuar = true;
//Validacion del lado del cliente
//iniciamos un bucle para validar todos los campos input y agregar un borde de color 
//cuando se envie el formulario con algun campo vacio
$("#contact_form input[required=true], #contact_form textarea[required=true]").each(function(){
$(this).css('border-color','');
if(!$.trim($(this).val())){ //si el campo esta vacio 
$(this).css('border-color','Red'); //cambiar el color del borde   
continuar = false; //Seteamos la bandera en false y detemos la ejecución
}
//si el if anterior valida correctamente pasamos a la siguiente validacion
//Usaremos una expresion regular para validar la estructura del email
var email_reg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/; 
if($(this).attr("type")=="email" && !email_reg.test($.trim($(this).val()))){
$(this).css('border-color','Red'); //Cambiamos el color del borde si no cumple la estructura   
continuar = false; //Seteamos la bandera en false y detemos la ejecución                
}
});
});

//restablecer los colores del borde establecidos con anterioridad y ocultar todos los mensajes de .keyup()
$("#contact_form  input[required=true], #contact_form textarea[required=true]").keyup(function(){
$(this).css('border-color','');
$("#result").slideUp();
});
});

La primera parte ya esta hecha, pero al probar el formulario nos daremos cuenta que no realiza ninguna acción, si vemos la consola del navegador observaremos este error:

Error jQueryEsto se produce por no haber agregado la llamada a la librería de jQuery, asi que procedemos a incluirla en la cabecera de nuestra pagina 

<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js">

  ahora al volver a probar nuestro formulario e intentar enviarlo sin completar los campo se iluminan los bordes con un color rojo indicando un error y si completamos los campos iluminados estos se restablecen.

validacíon jQueryBien ahora ya validamos correctamente, pero cuando realizamos el envío no sucede nada, pues bien ahora lo resolveremos.

Para enviar los datos por email, usaremos el método mail() de PHP, este método de php es lo mas básico que podríamos implementar y mas sencillo.

Desde nuestro script jQuery mediante ajax enviaremos los datos del formulario a nuestro nuevo archivo php (contact_me.php) para procesarlos y enviar el mail (al fin).

Agregamos los siguiente a nuestro script después  del método .eatch().

//Si llegamos a este punto, ¡Todo se ve bien! proceder...
if(continuar){
//obtenemos los valores de los campos de entrada para ser enviados al servidor
post_data = {
'user_name'    : $('input[name=name]').val(),
'user_email'   : $('input[name=email]').val(),
'country_code' : $('input[name=phone1]').val(),
'phone_number' : $('input[name=phone2]').val(),
'subject'      : $('select[name=subject]').val(),
'msg'          : $('textarea[name=message]').val()
};

//Enviar datos mediante Ajax al servidor
$.post('contact_me.php', post_data, function(response){  
if(response.type == 'error'){ //Cargamos datos en formato JSON de validacion del lado del servidor para mostrar los mensajes de error.
output = '<div class="error">'+response.text+'</div>';
}else{
output = '<div class="success">'+response.text+'</div>';
//Restablecemos los valores de todos los campos del formulario
$("#contact_form  input[required=true], #contact_form textarea[required=true]").val('');
$("#contact_form #contact_body").slideUp(); //Ocultamos el formulario y mostramos un mensaje de éxito
}
$("#contact_form #contact_results").hide().html(output).slideDown();
}, 'json');
}

Ahora crearemos el archivo

contact_me.php

  y agregamos el siguiente código.

<?php
if($_POST){
//A quien le llegara el email
$to_email = "mail@localhost";    
//Primera validacion y basica, comprobar si es una petición AJAX
if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
$output = json_encode(array( //crear datos JSON
'type' => 'error',
'text' => 'Perdon, las peticiones deben ser de tipo Ajax'
));
die($output);
}
//Limpiamos los datos de entrada utilizando filter_var() de PHP5
$user_name    = filter_var($_POST["user_name"], FILTER_SANITIZE_STRING);
$user_email   = filter_var($_POST["user_email"], FILTER_SANITIZE_EMAIL);
$country_code = filter_var($_POST["country_code"], FILTER_SANITIZE_NUMBER_INT);
$phone_number = filter_var($_POST["phone_number"], FILTER_SANITIZE_NUMBER_INT);
$subject      = filter_var($_POST["subject"], FILTER_SANITIZE_STRING);
$message      = filter_var($_POST["msg"], FILTER_SANITIZE_STRING);


//Aunque validamos los datos con jQuery, si por alguna razon el
//navegador del visitante tiene javascript desahilitado no funcionara la validacion
//asi que realizaremos validación adicional con php del lado del servidor
if(strlen($user_name)<4){ //Si la longitud es menor que 4, devolvemos el error con JSON
$output = json_encode(array('type'=>'error', 'text' => 'El nombre es demasiado corto o está vacío!'));
die($output);
}
if(!filter_var($user_email, FILTER_VALIDATE_EMAIL)){ //validacion de email
$output = json_encode(array('type'=>'error', 'text' => 'Por favor ingrese un email valido!'));
die($output);
}
if(!filter_var($country_code, FILTER_VALIDATE_INT)){ //Chequear que el campo codigo pais es un numero valido
$output = json_encode(array('type'=>'error', 'text' => 'Introduzca sólo dígitos en el código de país'));
die($output);
}
if(!filter_var($phone_number, FILTER_SANITIZE_NUMBER_FLOAT)){ //Chequear que el telefono sea un numero valido
$output = json_encode(array('type'=>'error', 'text' => 'Introduzca sólo dígitos en el número de teléfono'));
die($output);
}
if(strlen($subject)<3){ //Nos aseguramos que el asunto no este vacio
$output = json_encode(array('type'=>'error', 'text' => 'El asunto es requerido'));
die($output);
}
if(strlen($message)<3){ //Revisamos que el mensaje no esta vacio
$output = json_encode(array('type'=>'error', 'text' => 'Mensaje demasiado corto! Por favor, introduzca algo mas.'));
die($output);
}


//cuerpo del email
$message_body = $message."\r\n\r\n-".$user_name."\r\nEmail : ".$user_email."\r\nPhone Number : (".$country_code.") ". $phone_number ;
//enviamos el email con php.
$headers      = 'From: '.$user_name.'' . "\r\n" .'Reply-To: '.$user_email.'' . "\r\n" .'X-Mailer: PHP/' . phpversion();
$send_mail    = mail($to_email, $subject, $message_body, $headers);

if(!$send_mail){
//Si el correo no pudo ser enviado o recibimos error de salida.
//Compruebe la configuración de correo electrónico PHP (si es que alguna vez sucede )
$output = json_encode(array('type'=>'error', 'text' => 'No se pudo enviar el correo! Por favor, compruebe la configuración de PHP mail.'));
die($output);
}else{
$output = json_encode(array('type'=>'message', 'text' => 'Hola '.$user_name .' Gracias por tu email, pronto nos contactaremos.'));
die($output);
}
}
?>

Ahora ya podemos realizar un prueba del envío. No olviden cambiar la dirección de email donde llegaran los mensajes en la linea 4 del archivo contact_me.php.

Otra cosa importante es el hecho que si prueban el formulario en un servidor local no les llegara el mensaje al correo configurado y si miran la consola del navegador verán un mensaje similar al siguiente.

<br />
<b>Warning</b>:  mail(): Failed to connect to mailserver at &quot;localhost&quot; port 25, verify your
 &quot;SMTP&quot; and &quot;smtp_port&quot; setting in php.ini or use ini_set() in <b>D:\USBWebserver
 v8.6\root\ajaxcontact\contact_me.php</b> on line <b>54</b><br />
{"type":"error","text":"No se pudo enviar el correo! Por favor, compruebe la configuraci\\u00f3n mail
 en su archivo php.ini."}

Esto es por que nuestros computadores hogareños no cuentan con un servidor de email configurado para poder enviar los email a otros servidores (gmail,yahoo, etc), pero en un hosting publico no deberíamos tener problema.

Actualización 21/06/2016

Para realizar pruebas en ambientes locales leer el siguiente post Como probar envios de eamil en servidor local

Descargar

Referencias

Paleta de Colores
Método .click() jQuery
Método mail PHP
jQuery.ajax()
filter_var PHP
filter_sanitize PHP

Formulario multi pasos con CSS y Jquery

Vamos a ver la forma de crear una sencillo formulario  del tipo multipaso, muy útil cuando tenemos formularios muy extensos o con demasiados campos, utilizaremos Jquery easing para animar la transición de las diferentes etapas o partes de las que se compondrá y le daremos el toque artístico con un poco de CSS (no esperen mucho, no soy bueno para el CSS).

Bueno lo primero sera confeccionar nuestro formulario, para ello utilizaré el siguiente código, el cual no presenta secretos.

En primer lugar definimos la cantidad de pasos para confeccionar una barra de progreso, para mantener informado al usuario y evitar que deje el formulario abandonado y perdamos trafico,  en este ejemplo serán 3 (Configurar tu cuenta, Perfil Social y Detalles Personales).

<form id="formulario">
<!-- progreso -->
<ul id="progreso">
<li class="active">Configurar tu cuenta</li>
<li>Perfil Social</li>
<li>Detalles Personales</li>
</ul>
</form>

La barra de progreso sera una simple etiqueta ul  con un id llamado progreso, con sus correspondientes etiquetas li (tantas como pasos tenga el formulario) [highlight color=yellow]no olvidar asignar la clase active al primer li[/highlight] que mediante jQuery y CSS posteriormente la dotaremos de vida.

Luego de definir los step o pasos del formulario, creamos diferentes campos fieldsets para contener cada paso y dentro todo lo que se requiera (inputs, h2, h3, p, label, etc).

<!-- fieldsets -->
<fieldset>
    <h2 class="fs-title">Crear su cuenta</h2>
    <h3 class="fs-subtitle">Paso 1</h3>
    <input type="text" name="email" placeholder="Email" />
    <input type="password" name="pass" placeholder="Password" />
    <input type="password" name="cpass" placeholder="Confirmar Password" />
    <input type="button" name="next" class="next action-button" value="Next" />
</fieldset>
<fieldset>
    <h2 class="fs-title">Perfil social</h2>
    <h3 class="fs-subtitle">Tu presencia en las redes</h3>
    <input type="text" name="twitter" placeholder="Twitter" />
    <input type="text" name="facebook" placeholder="Facebook" />
    <input type="text" name="gplus" placeholder="Google Plus" />
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
</fieldset>
<fieldset>
    <h2 class="fs-title">Detalles Personales</h2>
    <h3 class="fs-subtitle">Nunca venderemos tu informaci&oacute;n personal</h3>
    <input type="text" name="fname" placeholder="Nombre" />
    <input type="text" name="lname" placeholder="Apellido" />
    <input type="text" name="phone" placeholder="Telefono" />
    <textarea name="address" placeholder="Direcci&oacute;n"></textarea>
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="submit" name="submit" class="submit action-button" value="Submit" />
</fieldset>

En cada fieldset, adicional a los campos que requiramos, debemos agregar un input tipo button para avanzar de paso en paso y otro para retroceder (según corresponda), por tanto en este ejemplo necesito agregar uno el primer fieldset para avanzar, dos al segundo y uno para retroceder en el ultimo junto a uno tipo submit.
Si probamos el código obtendremos una simple pagina de fondo blanco con un formulario donde veremos todos los campos así.

Un toque de sensibilidad

Ahora lo principal es hacer mas vistoso nuestro formulario, para ello sacamos nuestros dotes artísticos (mas de alguien fumara algo para encontrar su inspiración xD) y nos zambullimos en CSS, yo no tengo estudios formales en CSS, pero la web es basta y repleta de información al respecto, al final de este articulo les dejare algunos link relacionados para el que desee profundizar alguno de los temas tratados en este post.

Primero importaremos una fuente tipografica desde el CDN de fuentes de google, yo usare la fuente Montcerrat, pero pueden usar la que estimen, desde google fonts podran navegar, buscar y elegir la que mas les agrade.

/*importamos una fuente personalizada desde google*/
@import url(http://fonts.googleapis.com/css?family=Montserrat);

Un pequeño reset de estilos al documento,  sera muy básico.

/*reset basico*/
* {margin: 0; padding: 0;}

Altura del documento html y aplicamos un combo de imagen como patern + gradient, cave señalar que la mayoría de CSS que usaremos, no aplica en internet explorer, esto debido a su incompatibilidad con esta versión de CSS 3 (pero bueno a quien le importa esos dinosaurio xD).

html {
    height: 100%; /*Image only BG fallback*/
    background: url('bitmaps/gs3.png'); /*background = combo gradient + imagen pattern*/
    background: linear-gradient(rgba(196, 102, 0, 0.2), rgba(155, 89, 182, 0.2)), url('bitmaps/gs3.png');
}

A pesar que mencione que no funcionaba bien en internet explorer  debemos asegurarnos que los otros navegadores entiendan nuestra codificación de estilos y para ello utilizaremos los prefijos para sus respectivos motores de render:

[checklist]
  • -webkit- : Para la familia Chrome / Chromium y Safari
  • -moz- : Para Mozilla Firefox y derivados
  • -o- : Para Opera (o si, aun existe)
  • -ms-: Para internet explorer 9 (pero linear-gradient no funciona bien en ie)
[/checklist]
background: -webkit-linear-gradient(rgba(196, 102, 0, 0.2), rgba(155, 89, 182, 0.2)), url('bitmaps/gs3.png');
background: -moz-linear-gradient(rgba(196, 102, 0, 0.2), rgba(155, 89, 182, 0.2)), url('bitmaps/gs3.png');
background: -o-linear-gradient(rgba(196, 102, 0, 0.2), rgba(155, 89, 182, 0.2)), url('bitmaps/gs3.png');
background: -ms-linear-gradient(rgba(196, 102, 0, 0.2), rgba(155, 89, 182, 0.2)), url('bitmaps/gs3.png');

Aplicamos la fuente importada

body {
    font-family: montserrat, arial, verdana;
}

Ahora el formulario y su contenido

/*estilo formulario*/
#formulario {
    width: 400px;
    margin: 50px auto;
    text-align: center;
    position: relative;
}
#formulario fieldset {
    background: #ffffff;
    border: 0 none;
    border-radius: 3px;
    -webkit-box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.4);
    box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.4);
    padding: 20px 30px;
    width: 80%;
    margin: 0 10%; /*Posicionamos todos los fieldset uno encima del otro*/
    position: absolute;
}
/*Ocultamos todos menos el primer fieldset*/
#formulario fieldset:not(:first-of-type) {
    display: none;
}
/*inputs*/
#formulario input,#formulario textarea {
    padding: 15px;
    border: 1px solid #ccc;
    border-radius: 3px;
    margin-bottom: 10px;
    width: 100%;
    font-family: montserrat;
    color: #2C3E50;
    font-size: 13px;
}
/*buttons*/
#formulario .action-button {
    width: 100px;
    background: #27AE60;
    font-weight: bold;
    color: white;
    border: 0 none;
    border-radius: 1px;
    cursor: pointer;
    padding: 10px 5px;
    margin: 10px 5px;
}
#formulario .action-button:hover,#formulario .action-button:focus {
    -webkit-box-shadow: 0 0 0 2px white, 0 0 0 3px #27AE60;
    box-shadow: 0 0 0 2px white, 0 0 0 3px #27AE60;
}
/*headings*/
.fs-title {
    font-size: 15px;
    text-transform: uppercase;
    color: #2C3E50;
    margin-bottom: 10px;
}
.fs-subtitle {
    font-weight: normal;
    font-size: 13px;
    color: #666;
    margin-bottom: 20px;
}

Solo resta la parte superior del formulario, donde se marcan los pasos:

/*progreso*/
#progreso {
    margin-bottom: 30px;
    overflow: hidden; 
    counter-reset: step; /*CSS contador para numerar los pasos, lo aprendi en http://www.w3schools.com/*/
}
#progreso li {
    list-style-type: none;
    color: white;
    text-transform: uppercase;
    font-size: 9px;
    width: 33.33%;
    float: left;
    position: relative;
}
#progreso li:before {
    content: counter(step);
    counter-increment: step;
    width: 20px;
    line-height: 20px;
    display: block;
    font-size: 10px;
    color: #333;
    background: white;
    border-radius: 3px;
    margin: 0 auto 5px auto;
}
/*conectores de progreso*/
#progreso li:after {
    content: '';
    width: 100%;
    height: 2px;
    background: white;
    position: absolute;
    left: -50%;
    top: 9px;
    z-index: -1; /*lo pone detrás de los números*/
}
#progreso li:first-child:after {
    /*el conector no es necesario antes de que el primer paso*/
    content: none; 
}
/*marca activo/completado los pasos en verde*/
/*El numero del paso y el conecto quedaran en verde*/
#progreso li.active:before,#progreso li.active:after {
    background: #27AE60;
    color: white;
}

Con esto hemos terminado la parte «artistica» de nuestro formulario. Si probamos nuestro formulario notaran que se ve bien esteticamente, que solo vemos la primera parte del formulario, pero al darle click al boton Next, no pasa nada, ahora le daremos vida con un poco de JQuery.

Crearemo un nuevo archivo con extension js, llamenlo como quieran, yo lo llamare funciones.js

$(document).ready(function(){
//jQuery time
var current_fs, next_fs, previous_fs; //fieldsets
var left, opacity, scale; //propiedades fieldset que vamos a animar
var animating; //

$(".next").click(function(){
    current_fs = $(this).parent();
    next_fs = $(this).parent().next();

    //activar el siguiente paso en progreso usando el índice de next_fs
    $("#progreso li").eq($("fieldset").index(next_fs)).addClass("active");

    //mostrar el siguiente fieldset
    next_fs.show(); 
    //ocultar el fieldset actual con estilo
    current_fs.animate({opacity: 0}, {
        step: function(now, mx) {
            //como la opacidad de current_fs está reducida a 0 - almacenado en "now"
            //1. escala current_fs hasta 80%
            scale = 1 - (1 - now) * 0.2;
            //2. traer next_fs desde la derecha (50%)
            left = (now * 50)+"%";
            //3. aumentar la opacidad de next_fs a 1 a medida que avanza
            opacity = 1 - now;
            current_fs.css({'transform': 'scale('+scale+')'});
            next_fs.css({'left': left, 'opacity': opacity});
        }, 
        duration: 800, 
        complete: function(){
            current_fs.hide();
        }, 
        //Esto viene del plugin easing
        easing: 'easeInOutBack'
    });
});

$(".previous").click(function(){
    current_fs = $(this).parent();
    previous_fs = $(this).parent().prev();

    //des-activar paso actual en progreso
    $("#progreso li").eq($("fieldset").index(current_fs)).removeClass("active");

    //mostrar el fieldset anterior
    previous_fs.show(); 
    //ocultar el fieldset actual con estilo
    current_fs.animate({opacity: 0}, {
        step: function(now, mx) {
            //as the opacity of current_fs reduces to 0 - stored in "now"
            //1. escalar previous_fs de 80% a 100%
            scale = 0.8 + (1 - now) * 0.2;
            //2. take current_fs to the right(50%) - from 0%
            left = ((1-now) * 50)+"%";
            //3. increase opacity of previous_fs to 1 as it moves in
            opacity = 1 - now;
            current_fs.css({'left': left});
            previous_fs.css({'transform': 'scale('+scale+')', 'opacity': opacity});
        }, 
        duration: 800, 
        complete: function(){
            current_fs.hide();
        }, 
        //Esto viene del plugin easing
        easing: 'easeInOutBack'
    });
});

$(".submit").click(function(){
    return false;
})

});

Ahora si hemos terminado, si desean que su formulario envié deben editar la ultima función del script.

Adicionalmente deben refererciar al plugin easing porque ocuparemos uno de sus metodos para animar nuestro formulario.

<!-- jQuery easing plugin -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js" type="text/javascript"></script>

A continuacion les dejare un enlace con una demo de este formulario y un link donde podrán descargar el ejemplo completo listo para usar o editar a su conveniencia.

Referencias

 

Demo

Ver Demostración

Descargar ejemplo

Como saber cuando google bot visita nuestro sitio web

google robot

Sí deseas saber el momento exacto y por cuales páginas ha pasado el robot de google (Googlebot) en su o sus sitios web. Solo debes utilizar el siguiente código en el header del sitio y cuando el bot de google aparesca recibiran un email con la IP, navegador y url destino de la araña o robot de google.

Deben cambiar la dirección de email por la suya (obvio), si no les funciona puede ser que su hosting o servidor tengan la funcion mail de php truncada, en ese caso pueden usar la libreria phpmailer ampliamente documentada en internet:

if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'Googlebot' ) != false ){
    mail('miemail@midominio.com', 'Paso de Googlebot', '
        IP: '.$_SERVER['REMOTE_ADDR'].' -
        Sistema operativo y navegador: '.$_SERVER['HTTP_USER_AGENT'].' -
        Web destino: '.$_SERVER['REQUEST_URI'].''
    );
}

y el correo que recibiremos sera parecido a la siguiente captura:

Paso de Googlebot

Gateway de correo con filtro antispam y antivirus

Postfix, Clamav y Spamassassin

Ni virus ni spam. Un servicio de correo a la altura de los tiempos que corren.

Bienvenido al mundo de los servicios de correo electrónico, servicio que aporta emociones tales como usuarios enfadados si no les llega corre, enfadados si les llega virus, enfadados si les envían documentos grandes… Siempre están enfadados o casi siempre… Así que armase de paciencia o, tal vez, ya no le haga falta este artículo. Si, la cosa ha evolucionado y quizás con lo lea aquí, pueda librarse de sus “rugidos”. Vamos a ver, a continuación, como montar un gateway de correo que obligue a pasar todos los mensajes por un filtro antispam y antivirus.

Si solo desea ver la parte técnica, salte a la sección “Implementación”.

El Problema

Con mi antiguo sistema de correo entraba y salía todo tipo de mensajes de correo que cumpliera el RFC. Este sistema de correo se dividía en dos partes: Servidor de correo donde estaban los buzones y gateway de correo con presencia en Internet.

Cada uno tenia sus problemas y, a continuación, les hago participes de ellos.

Del gateway de correo puedo decir que:
No le importaba que un correo tuviera virus. Aunque tenemos un antivirus por puesto de trabajo, les puedo asegurar que por el correo se camuflaban con bastante éxito. No le importaba que un correo fuera spam, lo cual causaba que ambos servidores tuvieran un gran trabajo, tanto el gateway recibiéndolos como el servidor de buzones, en identificar si existía tal dirección de correo en el servicio.

El servidor de buzones tenía otro gran problema: estaba perfectamente integrado en varios servicios y por lo tanto, cambiarlo hubiera supuesto mucho dinero y tiempo.
Para acabarla de rematar, era la solución de un proveedor de software propietario, así que el resto de la canción mejor no se la cueto.

La solución

La solución pasaba por tener un sistema de correo electrónico que fuera rápido, flexible, seguro y eficiente y que, por supuesto, antes de aceptar el correo hiciera varias comprobaciones tales como si existía la dirección de correo, si tenia virus, si era spam, etc.
Por ultimo, mientras se llegaba al nuevo sistema, este debía convivir con el antiguo sin causar ningún tipo de trastorno al usuario. Pero para eso tenemos el DNS, ¿no?

Elección del producto
La elección del MTA barajó por los siguientes productos:

Courier
Exim
Postfix
Qmail
Sendmail

Courier fue descartado por su inmadurez o falta de experiencia que, a mi modo de ver, todavía tiene para confiar en dar servicio con el. De Exim diré que no encontré documentación suficiente y, por lo tanto, no podía flexibilizarlo a mis necesidades y tampoco encontré la forma que comprobara si existía la dirección de correo antes de recoger el correo.
Sendmail, ¿la razón? Es un dinosaurio. La configuración es lo mas parecido a aprender un lenguaje de programación. Es monolítico y, por ultimo, su integración con otros paquetes alguna vez me había dado algún susto desagradable.

Me quede en la eterna duda… ¿Qmail o Postfix? Hace tiempo elegí Qmail y además escribí sobre ello pero de humanos es errar y de sabios es rectificar. Ya no lo uso y voy a dar mis motivos.
Primeramente, la actitud del creador de Qmail no es, según mi criterio, una actitud realista en el mundo donde yo me muevo, que es el de la empresa.
Seguidamente, depender de módulos de terceros para poder integrar a otros productos qué hagan todo aquello que se pueda necesitar, hace que su indicador de riesgo/gasto de explotación aumente de forma bestial, cosa que yo no me puedo permitir. Por lo cual, elegí Postfix.

La elección del antivirus fue un tanto curiosa. Sin decir marcas, ya había tenido experiencias con algunos que por supuesto no sabia si era mejor el remedio que la enfermedad. Entones me quedaba con dos: Karpersky y Clamav. Me incline por Clamav debido a su coste final, es decir, 0 $. Si ambos productos son buenos, la balanza se mueve de un lado a otro por los costes. El gestor de anti-spam lo elegí como vulgarmente se dice, al azar……

CONTINUARA