Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=54c4c5a8-849e-41e0-9727-b9b118e2c279

Cómo enviar correo electrónico con Java a través de GMail

Imagen ornamental

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 es un poco especial para esto, ya que 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"

Este eufemismo es el que utiliza Google para referirse a 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.

Es un ajuste que está en la zona de seguridad de tu cuenta de Google, en la parte de abajo del todo de la sección de autenticación, pero existe también un acceso directo a este ajuste en exclusiva:

Interfaz de selección para permitir aplicaciones menos seguras

Si no lo marcas, cuando intentes 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 cambiado este ajuste ya podrás utilizar sin problema la funcionalidad que te explicamos 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) {
    // Esto es lo que va delante de @gmail.com en tu cuenta de correo. Es el remitente también.
    private String remitente = "nomcuenta";  //Para la dirección [email protected]

    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", "miClaveDeGMail");    //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, 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, clave);
        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, 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.

campusMVP campusMVP es la mejor forma de aprender a programar online y en español. En nuestros cursos solamente encontrarás contenidos propios de alta calidad (teoría+vídeos+prácticas) creados y tutelados por los principales expertos del sector. Nosotros vamos mucho más allá de una simple colección de vídeos colgados en Internet porque nuestro principal objetivo es que tú aprendas. Ver todos los posts de campusMVP

No te pierdas ningún post

Únete gratis a nuestro canal en Telegram y te avisaremos en el momento en el que publiquemos uno nuevo.

Archivado en: Lenguajes y plataformas

La mejor formación online para desarrolladores como tú

Comentarios (11) -

Buenas, estoy teniendo problemas cuando ejecuto la aplicacion, me tira el siguiente error:

com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1;
  nested exception is:
  java.net.ConnectException: Connection timed out: connect
  at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2209)
  at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:740)
  at javax.mail.Service.connect(Service.java:366)
  at javax.mail.Service.connect(Service.java:246)
  at jmsptp.Prueba.mail2(Prueba.java:32)
  at jmsptp.Prueba.main(Prueba.java:46)
Caused by: java.net.ConnectException: Connection timed out: connect
  at java.net.DualStackPlainSocketImpl.connect0(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
  at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
  at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
  at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
  at java.net.PlainSocketImpl.connect(Unknown Source)
  at java.net.SocksSocketImpl.connect(Unknown Source)
  at java.net.Socket.connect(Unknown Source)
  at java.net.Socket.connect(Unknown Source)
  at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:353)
  at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:239)
  at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2175)
  ... 5 more

Responder

campusMVP
campusMVP

Hola Maxi:

En este caso no se trata de un error de código sino de comunicaciones. El error te dice que no puede conectar al puerto 465.

Parece que te estás intentando conectar al puerto 465, y no al puerto 587 que es el que debes utilizar para GMail, según indica el artículo. Tienes que especificarlo:

props.put("mail.smtp.port", "587");

Verifica también que el firewall o proxy a través del que sales a Internet no tiene cerrado el acceso a ese puerto.

Responder

albin arias
albin arias

Que tal amigo, me preguntaba si podias ayudarme con algo
me sale que la clave no esta definida y que destinatario no puede ser convertido a "address" o mail.

y esto también
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: javax.mail.internet.MimeMessage.addRecipient
  at enviarmail.Enviarmail.enviarConGMail(Enviarmail.java:37)
  at enviarmail.Enviarmail.main(Enviarmail.java:55)
C:\Users\Andrea\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

Responder

Hola:

¿Seguro que la dirección de email es correcta? Tiene pinta de ser eso.

Por otro lado ¿estás intentando a��adir más de un destinatario al mismo tiempo? Si es así debes llamar a addRecipient una vez por destinatario o bien meterlos a todos en una matriz y llamar a addRecipients (en plural). O usar  InternetAddress.parse para obtener una matriz de correos válidos a partir de una lista de direcciones separadas por comas.

Saludos.

Responder

Edisson Cardenas
Edisson Cardenas

Muchas Gracias!!!.   Me ha sido de mucha utilidad

Responder

Hola tengo un problema al ejecutar el programa me salta este error

Error: Could not convert socket to TLS

Responder

campusMVP
campusMVP

Hola:

Antes de nada, asegúrate de que has configurado GMail como se indica al principio del artículo y no deberías tener problema. Eso es muy importante o no te funcionará.

Si sigue ocurriendo: ¿tienes algún antivirus o proxy que pueda estar interfiriendo? Esto pasa a veces cuando hay algún tipo de elemento por el medio. El antivirus Avast al parecer a veces provoca esto.

Puedes evitar el error añadiendo esta línea:

props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

para forzar que se confíe en el certificado de GMail, pero es algo que no deberías necesitar en absoluto.

Saludos.

Responder

José Carlos
José Carlos

Hola Fijate que me tira este error

run:
Errorjavax.mail.MessagingException: [EOF]      <----------
Error
BUILD SUCCESSFUL (total time: 0 seconds)

Responder

Hola, podrias ayudarme para a partir de este ejemplo poder enviar tambien en el correo que mandas un adjunto o varios como puede ser un xlxs o un pdf?
Gracias

Responder

Hola:

Solo tendrías que añadir un cuerpo multi-parte y adjuntar lo que necesites, algo así:

messageBodyPart = new MimeBodyPart();
String archivo = "ruta/al/archivo.xlsx";
DataSource src= new FileDataSource(archivo);
messageBodyPart.setDataHandler(new DataHandler(src));
messageBodyPart.setFileName(archivo);
multipart.addBodyPart(messageBodyPart);

Luego añades esa nueva parte al mensaje:

message.setContent(multipart);

Con esto ya estaría.

Saludos!

Responder

Muchas gracias, lo he hecho asi parecido y funciona con el excel, con un pdf, con texto y con imagen.
Saludos

Responder

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.