Muchas aplicaciones que vas a desarrollar necesitarán enviar algún correo electrónico que otro de vez en cuando. Si necesitas hacer muchos envíos es mejor recurrir a servicios especializados, como por ejemplo Sendgrid o Mailgun, pero si lo único que quieres es poder enviar un correo muy de vez en cuando (por ejemplo, para un formulario de contacto en tu web o cuando se produzca un error), entonces puedes recurrir a soluciones más "rupestres" como la que te vamos a contar.
Precisamente por esta necesidad, una de las preguntas más frecuentes que se ven en foros sobre envío de correo es ¿cómo envío correo desde Java usando mi actual cuenta de GMail?.
La manera más sencilla es usando la API de JavaMail, pensada para enviar correo a través de SMTP a través de cualquier servidor.
Lo que ocurre es que GMail, al igual que muchos otros proveedores conocidos, por defecto no permite la conexión directa mediante usuario y clave a sus servidores de envío.
El motivo es que dispone de una API oficial para conectarse mediante la cuenta de Google y autenticar al usuario antes de enviar. Pero si queremos hacer uso del servidor SMTP para un envío directo, todavía podemos hacerlo.
Permitir aplicaciones "menos seguras" - Contraseñas de aplicaciones
De esta forma es como llama Google para referirse aplicaciones que, en lugar de usar la API de seguridad de Google y sus tokens, utilizan la vieja pareja "usuario-clave" para acceder al servicio.
De lo que se trata es de habilitar una clave exclusiva para acceder a un determinado servicio (en este caso el correo electrónico) desde una determinada aplicación. De este modo tenemos controladas esas claves y no usamos la nuestra propia, por lo que aunque sigue siendo más inseguro, no lo es tanto y nos permite usar el servicio desde aplicaciones externas sin que deban utilizar la API.
MUY IMPORTANTE: los siguientes ajustes solamente se pueden encontrar en cuentas que tengan activada la verificación en dos pasos y usen por tanto la app Authenticator de Google para autenticarse. Si no te aparece es porque no tienes activada esta opción de seguridad. Fíjate en que en la figura siguiente, mi cuenta tiene activada dicha modalidad.
Estas contraseñas de aplicación se encuentran en la zona de seguridad de tu cuenta de Google, al final del apartado "Iniciar sesión con Google":
pero existe también un acceso directo a este ajuste en exclusiva. Al entrar en esta opción, tras habernos autenticado, nos muestra un listado con las contraseñas de este tipo que hayamos creado anteriormente y un selector para crear una nueva:
En el primer desplegable elegimos Correo
como la aplicación para la que valdrá la contraseña, en el segundo elegiremos el tipo de dispositivo que vamos a usar para conectarnos, que será Otra (nombre personalizado)
como se ve en la figura, lo cual nos permitirá otorgarle un nombre que sea significativo (por ejemplo "Envío correo en app gestión" o algo así) y nos permita saber en el futuro para qué se usaba la contraseña. Al darle al botón Generar
se abre un nuevo diálogo modal que nos muestra la clave autogenerada:
Esa ristra de números es la contraseña que tendremos que utilizar en nuestro programa para poder enviar correo, siendo el usuario nuestra dirección de correo electrónico.
OJO: Anótala temporalmente para meterla en el programa, pues una vez que cierres el diálogo no tendrás forma de volver a verla.
En el futuro si ya no te hace falta o si ocurre algo y la clave se filtra por ahí y ya no la conoces tú solamente, puedes volver al mismo sitio y eliminarla desde la lista de contraseñas de aplicación:
Si no obtienes esta contraseña e intentas conectarte con la contraseña normal de la cuenta, al intentar enviar correo a través del servidor SMTP de GMail obtendrás el error:
"The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required"
Pero una vez obtenida la contraseña ya podrás utilizar sin problema la funcionalidad que te explico a continuación.
Nota: marcando esta funcionalidad se supone que tu cuenta está menos segura ya que ciertas aplicaciones no pasarían por la API de Google y sus tokens de autenticación. Y es cierto. Pero por otro lado si pierdes la clave de tu cuenta tendrás un problema de todos modos. Simplemente, si activas esta opción asegúrate de que guardas las credenciales a buen recaudo, y desde luego no las pongas en tu código y las distribuyas con tu aplicación, pues entonces seguro que las pierdes.
Enviar email a través de servidores SMTP con Java
Como decíamos antes, lo primero que tienes que asegurarte de que tienes la API de JavaMail disponible. Si tienes J2EE instalado, entonces no tienes que hacer nada pues ya dispones de dichas clases. En caso de no usar J2EE puedes descargarte los .jar
y añadirlos como dependencias a tu proyecto si utilizas un IDE como NetBeans, o bien asegurarte de que los tienes en el classpath
en caso de no utilizar IDE alguno.
Una vez hecho podemos definir una función como esta:
private static void enviarConGMail(String destinatario, String asunto, String cuerpo) {
//La dirección de correo de envío
String remitente = "[email protected]";
//La clave de aplicación obtenida según se explica en este artículo:
String claveemail = "1234567890123456";
Properties props = System.getProperties();
props.put("mail.smtp.host", "smtp.gmail.com"); //El servidor SMTP de Google
props.put("mail.smtp.user", remitente);
props.put("mail.smtp.clave", claveemail); //La clave de la cuenta
props.put("mail.smtp.auth", "true"); //Usar autenticación mediante usuario y clave
props.put("mail.smtp.starttls.enable", "true"); //Para conectar de manera segura al servidor SMTP
props.put("mail.smtp.port", "587"); //El puerto SMTP seguro de Google
Session session = Session.getDefaultInstance(props);
MimeMessage message = new MimeMessage(session);
try {
message.setFrom(new InternetAddress(remitente));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(destinatario)); //Se podrían añadir varios de la misma manera
message.setSubject(asunto);
message.setText(cuerpo);
Transport transport = session.getTransport("smtp");
transport.connect("smtp.gmail.com", remitente, claveemail);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
}
catch (MessagingException me) {
me.printStackTrace(); //Si se produce un error
}
}
Que se encargará de hacer los envíos. Luego podemos llamarla desde cualquier lugar de la siguiente manera:
public static void main(String[] args) {
String destinatario = "[email protected]"; //A quien le quieres escribir.
String asunto = "Correo de prueba enviado desde Java";
String cuerpo = "Esta es una prueba de correo...";
enviarConGMail(destinatario, asunto, cuerpo);
}
Lo que hará que se envíe un mensaje a la dirección especificada con el asunto y el cuerpo que hayamos indicado.
IMPORTANTE: nunca deberías incluir el nombre de usuario y la clave de la cuenta que usas para enviar, directamente en el código, puesto que el Bytecode es muy fácil de desofuscar y cualquiera podría verlos. En el caso de una aplicación web es mejor que los guardes externamente, en un archivo de configuración en el servidor o en variables de entorno (como se hace, por ejemplo, en Repl.it si lo quieres dejar almacenado), lejos del alcance de los visitantes. En una aplicación de escritorio lo mejor sería que solicitases esos datos a cada usuario y los guardases de manera local, pero nunca en el código.
Para facilitarte que lo pruebes, he creado este Repl.it que puedes utilizar cambiando los datos del remitente, el destinatario y la clave de la cuenta:
¡Espero que te resulte útil!