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, 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": 

La opción resaltada en la UI de GMail

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!

Fecha de publicación:
José Manuel Alarcón Fundador de campusMVP, es ingeniero industrial y especialista en consultoría de empresa. Ha escrito diversos libros, habiendo publicado hasta la fecha cientos de artículos sobre informática e ingeniería en publicaciones especializadas. Microsoft lo ha reconocido como MVP (Most Valuable Professional) en desarrollo web desde el año 2004 hasta la actualidad. Puedes seguirlo en Twitter en @jm_alarcon o leer sus blog técnico o personal. Ver todos los posts de José Manuel Alarcón
Archivado en: Lenguajes y plataformas

Boletín campusMVP.es

Solo cosas útiles. Una vez al mes.

🚀 Únete a miles de desarrolladores

DATE DE ALTA

x No me interesa | x Ya soy suscriptor

La mejor formación online para desarrolladores como tú

Comentarios (48) -

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

Buenas queria consultar porque me tira error en esta linea:
transport.connect("smtp.gmail.com", remitente, clave); (donde dice clave que es lo que va? la clave del remitente?)

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

Juan Sebastian
Juan Sebastian

Solo debes poner la linea así:
message.addRecipient(Message.RecipientType.TO, new InternetAddress(destinatario));

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

Daniel Villalobos
Daniel Villalobos

Si tenia el mismo problema y luego de intentar de todo simplemente baje el AVAST y listo funciono todo OK.!!

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

Me está saliendo este error:
javax.mail.MessagingException: 530 5.7.0 Must issue a STARTTLS command first. h82-v6sm26874093pfa.173 - gsmtp

Responder

Hola, utilizando la herramienta ECLIPSE estoy intentando enviar un mensaje via GMAIL con el siguiente código, y me está dando el error que aprecias mas abajo. ¿me podrías dar una solución?  
import java.util.*;
  import javax.mail.*;
  import javax.mail.internet.*;
  import javax.activation.*;
  
public class Enviarcorreo {
  
  

  
     public static void main(String [] args) {    
        // Recipient's email ID needs to be mentioned.
        String to = "[email protected]";

        // Sender's email ID needs to be mentioned
        String from = "[email protected]";

        // Assuming you are sending email from localhost
        //String host = "127.0.0.1";

        // Get system properties
        Properties properties = System.getProperties();

        // Setup mail server
        //properties.setProperty("mail.smtp.host", host);
        properties.put("mail.smtp.port", "587");
        // Get the default Session object.
        Session session = Session.getDefaultInstance(properties);

        try {
           // Create a default MimeMessage object.
           MimeMessage message = new MimeMessage(session);

           // Set From: header field of the header.
           message.setFrom(new InternetAddress(from));

           // Set To: header field of the header.
           message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

           // Set Subject: header field
           message.setSubject("This is the Subject Line!");

           // Now set the actual message
           message.setText("This is actual message");

           // Send message
           Transport.send(message);
           System.out.println("Sent message successfully....");
        } catch (MessagingException mex) {
           mex.printStackTrace();
        }
     }
  
  
}








ERRROORRR:

javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 587;
  nested exception is:
  java.net.ConnectException: Connection refused: connect
  at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1961)
  at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)
  at javax.mail.Service.connect(Service.java:295)
  at javax.mail.Service.connect(Service.java:176)
  at javax.mail.Service.connect(Service.java:125)
  at javax.mail.Transport.send0(Transport.java:194)
  at javax.mail.Transport.send(Transport.java:124)
  at Enviarcorreo.main(Enviarcorreo.java:47)
Caused by: java.net.ConnectException: Connection refused: 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:321)
  at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:237)
  at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1927)
  ... 7 more

Responder

Buenos días amigo, excelente post, ha estado todo muy bien explicado...
Pero si quiero enviar archivos adjuntos, cual sería la forma de hacerlo?

Responder

Hola Betsy:

Para adjuntar un archivo tienes que crear un DataHandler que lo gestione, así:

BodyPart parteAdjunto = new MimeBodyPart();
String nomArch = "/home/miUsuario/miarchivo.zip";
DataSource arch = new FileDataSource(filename);
parteAdjunto.setDataHandler(new DataHandler(arch));
parteAdjunto.setFileName(nomArch);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(textoDelMensaje);
multipart.addBodyPart(parteAdjunto);
message.setContent(multipart);
multipart.addBodyPart(parteAdjunto);

Saludos.

Responder

Hola!
Cuando ejecuté el programa desde netbeans si me funcionó y me envió el correo.
Lo compilé y cuabdo ejecuto desde el .jar no me envía el correo
Solución? Sugerencia? Gracias

Responder

campusMVP
campusMVP

Hola:

Tienes que empaquetar las dependencias con tu .jar para que vayan con éste y te funcionen. Échale un vistazo a la documentación de NetBeans: https://netbeans.org/kb/73/java/javase-deploy.html

Por otro lado si te da un error "java.lang.NoClassDefFoundError" puedes ver las posibles soluciones aquí: www.campusmvp.es/.../...deffounderror-en-java.aspx

Saludos.

Responder

Alejandro
Alejandro

Mira, me sale este error y no sé como solucionarlo
Couldn't connect to host, port: smtp.gmail.com, 587; timeout -1;
  nested exception is:
  java.net.ConnectException: Connection refused: connect
  at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2053)
  at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:697)
  at javax.mail.Service.connect(Service.java:364)
  at javax.mail.Service.connect(Service.java:245)
  at AmazonSESSample.enviarConGMail(AmazonSESSample.java:33)
  at AmazonSESSample.main(AmazonSESSample.java:46)
Caused by: java.net.ConnectException: Connection refused: connect
  at java.net.DualStackPlainSocketImpl.connect0(Native Method)
  at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
  at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
  at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
  at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
  at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
  at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
  at java.net.Socket.connect(Socket.java:589)
  at java.net.Socket.connect(Socket.java:538)
  at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:312)
  at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:236)
  at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2019)

Responder

Buenas tardes. Tengo una consulta, no he tenido problemas para nada con el codigo, mas bien queria saber si existe la forma de validar la direccion de correo antes de ser enviada, ¿con que fin? para saber si el correo digitado existe, ya que tengo mis usuarios que se equivocan al digitar.

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola Walter:

Para hacer eso tienes que usar otro tipo de técnicas. Aparte de, obviamente, validar con alguna expresión regular decente que el correo cumple con el formato que tiene que tener (primera barrera antes de que lo almacenes), para verificar que es un correo existente puedes establecer comunicación con el servidor de correo y mandar los comandos como si fueras a enviar el correo, pero sin enviarlo. Tendrías que enviar los comandos:

- EHLO
- MAIL FROM
- RCPT TO

si a este último recibes un código 250, es que la dirección existe (en principio), y podrías cortar la conexión con un comando QUIT.

Esto no garantiza al 100% que la dirección exista o no ya que puedes estar conectando con un servidor que tiene dirección catch-all y todas son válidas, o lo contrario: que implemente listas grises y la primera vez que conectas deniegue la entrega de correo, pero en un porcentaje muy alto de los casos puedes validar las direcciones de estas manera.

Hay servicios como https://clearout.io/ que te lo dan hecho y tienen una API que puedes llamar y te garantizan un 98% de precisión, pero con si programas el método anterior lo puedes hacer tú mismo de manera bastante sencilla.

Saludos.

Responder

tengo problemas al tratar de declarar la variable tipo Session, no reconoce el metodo, teno ya la dependencia instalada pero hay algo mas que deberia de importar?
gracias de antemano

Responder

Hola Jonathan:

¿Seguro que tienes todos los "import" necesarios?:

import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

Saludos.

Responder

trato de usar el codigo pero me manda error Exception in thread "main" java.lang.NoClassDefFoundError: javax/activation/DataHandler, ademas el import javax.activatio.*; me dice que no existe el paquete javax.activation

Responder

Hola trato de usar el codigo y me sale error Exception in thread "main" java.lang.NoClassDefFoundError: javax/activation/DataHandler y aparte me sale  import javax.activatio.* no existente?

Responder

me aparece el siguiente error, si alguien podria ayudarme se lo agradeceria.
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger
  at javax.mail.Session.initLogger(Session.java:227)
  at javax.mail.Session.<init>(Session.java:212)
  at javax.mail.Session.getDefaultInstance(Session.java:315)
  at javax.mail.Session.getDefaultInstance(Session.java:355)
  at correo.c.enviarConGMail(c.java:25)
  at correo.c.main(c.java:50)
Caused by: java.lang.ClassNotFoundException: com.sun.mail.util.MailLogger
  at java.net.URLClassLoader.findClass(Unknown Source)
  at java.lang.ClassLoader.loadClass(Unknown Source)
  at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
  at java.lang.ClassLoader.loadClass(Unknown Source)
  ... 6 more

Responder

Hola Felipe:

Lo que te ocurre es que te falta incluir una referencia a la API de Java Mail. ¿Estás usando Java SE o Java EE? (mira aquí si no tienes clara la diferencia: www.campusmvp.es/.../...ones-implementaciones.aspx).

El caso es que Java Mail viene incluido de serie con Java EE, pero no viene incluido con Java SE. Si usas Java SE tendrás que añadir la referencia al .jar a tu proyecto (javaee.github.io/.../#Download_JavaMail_Release) y ya te funcionará.

Saludos.

Responder

Hola mi estimado, te cuento que tengo un error medio raro. Seguí tal cual tu tutorial pero me tira el siguiente error:

javax.mail.NoSuchProviderException: No provider for smtp

No se que podría llegar a ser.

Se agradece la ayuda.

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola Rodrigo:

Eso tiene toda la pinta de ser porque estás usando una versión muy vieja de JavaMail.

Actualízate a la última versión y seguramente se arreglará.

Saludos.

Responder

eso mismo pensé y por eso en mi pom puse la sig dependencia:

<!-- mvnrepository.com/.../javax.mail-api -->
<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.2</version>
</dependency>


Pero sigue tirando el mismo error

Responder

José Manuel Alarcón
José Manuel Alarcón

Mmmm... ¿el protocolo lo tienes en minúsculas: "smtp"? A veces puede ser eso...

no sé qué decirte, lo siento...

Si lo soluciones comparte con nosotros la solución. Gracias.

Saludos.

Responder

Probé en minuscula, mayúscula pero todo igual. Muchas gracias de todos modos. Si lo puedo solucionar obviamente comparto la solución.
Gracias.

Responder

Holaaa, A mi me sale este error en la linea para conectar...

transport.connect("smtp.gmail.com", remitente, clave);

Caused by: java.lang.NoSuchMethodError: sun.security.ssl.SSLSessionImpl.<init>(Lsun/security/ssl/ProtocolVersion;Lsun/security/ssl/CipherSuite;Ljava/util/Collection;Lsun/security/ssl/SessionId;Ljava/lang/String;I)V
  at sun.security.ssl.ClientHandshaker.serverHello(ClientHandshaker.java:709)
  at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
  at sun.security.ssl.Handshaker.processLoop(Handshaker.java:984)
  at sun.security.ssl.Handshaker.process_record(Handshaker.java:919)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
  at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
  at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:619)
  at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:546)
  at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2135)
  at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:738)
  at javax.mail.Service.connect(Service.java:366)
  at javax.mail.Service.connect(Service.java:246)
  at Controller.ManagedCorreo.enviarConGMail(ManagedCorreo.java:35)

No se en que fallo, y he digitado lo que has puesto en el tutorial ...
pero... cambie esta linea

           message.addRecipient(Message.RecipientType.TO, destinatario);

por esta, porque me decia que no se puede poner String en addRecipient

            message.addRecipient(Message.RecipientType.TO, new InternetAddress(destinatario));

Responder

campusMVP
campusMVP

Hola:

¿Qué estás usando exactamente? ¿Glassfish? Por lo visto Glassfish tiene un problema de conflictos de clases que provoan precisamente esa excepción: https://stackoverflow.com/a/52479362

Saludos.

Responder

Hola! Tengo el siguiente código

private static void enviarGmail(String destinatario) {
        String remitente = "helpet";
        String asunto = "Confirmación de correo";
        String clave = "helpet";
        String cuerpo = "Bienvenido";

        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", clave);    //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
        props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

        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);
            try (Transport transport = session.getTransport("smtp")) {
                transport.connect("smtp.gmail.com", remitente, clave);
                transport.sendMessage(message, message.getAllRecipients());
            }
        } catch (MessagingException me) {
            me.printStackTrace();   //Si se produce un error
        }
    }

Y también una llamada a este método desde la propia clase
enviarGmail(email);

No me salta ningún error, pero tampoco me llega ningún mensaje al correo. ¿Qué estoy haciendo mal?

Responder

Cristhian Galeano
Cristhian Galeano

Que tal amigo. Buen articulo que ría preguntar, si me puedes ayudar con información acerca de esta propiedad y su uso: mail.smtp.ssl.trust con valor (*), la he implementado como solución a un error.

Gracias

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola:

Eso significa que quieres confiar en el certificado de cualquier host, o sea, básicamente que te da igual de dónde venga el certificado SSL del servidor al que te conectas:

javaee.github.io/.../package-summary.html#:~:text=mail.smtp.ssl.trust,certificate%20the%20server%20presents.

Normalmente lo usarás con mail.smtp.ssl.enable.

Saludos,

Responder

Marcos Medina
Marcos Medina

Amigos ya no tiene caso aprender mail.jar (por lo menos para Gmail) porque Google ya anuncio que la opcion "Permitir aplicaciones menos seguras" sera elimada por la compañia.  :(

Responder

campusMVP.es
campusMVP.es

Hola marcos:

En efecto: ya tenemos una nota hace más de 2 años en el artículo, advirtiendo de ello. De todos modos todo lo explicado sigue siendo válido para el uso de otros servidores de envío, tanto propios como de terceros (estilo Mailjet, Sendgrid, Xeptomail, Mandrill, Amazon SES, etc...)

Saludos.

Responder

Hola Marcos,

La solución es usar una contraseña de aplicación que te facilita Google. Esta función lo encuentras en el apartado de seguridad de tu cuenta de google (debes tener habilitada la autenticación en dos pasos para activar la función de generar una contraseña de aplicación). Esa contraseña lo ingresas en tu código ;)

Responder

¿lo habéis probado?
Yo no se hacerle funcionar con este método. He creado la contraseña de aplicación pero sigo obteniendo el error de conexión.
Tengo muchas dudas sobre éste método. Dicha contraseña debe ser la que tenga la cuenta de correo?. Si es así, debería ser con la que intente hacer la conexión imagino.
En fin, si alguien ha intentado mandar un email desde javamail con estos cambios de google, le rogaría que me ayudara un poco porque ando despistado y toda la información que encuentro es anterior en el tiempo pero ninguna con la nueva situación de Gmail.
Gracias.

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola:

Este contenido ya tiene mucho tiempo. La parte de envío funciona bien, pero como indica el propio post, en GMail ya no es posible utilizar "Aplicaciones menos seguras"". Lo que tienes que hacer es generar una clave de aplicación para el envío de correo, que se hace en el mismo sitio, pero te dejo un acceso directo:

https://myaccount.google.com/apppasswords

Ahí eliges "Mail" como aplicación y en dispositivo "Otro (nombre personalizado)" y le das el nombre de tu aplicación. Pulsas el botón "Generar" y ya tienes una clave de acceso menos seguro, específica para esa aplicación, que puedes usar con el código del post.

Saludos.

Responder

José Manuel Alarcón
José Manuel Alarcón

Hola de nuevo:

He retocado el artículo para explicar paso a paso cómo obtener la clave de aplicación que necesitas. Y he añadido un Repl.it pare que cualquiera pueda probar el código sin tener que instalar nada, online, cambiando eso sí los datos para enviar correo.

Saludos!

Responder

Hola. Te cuento que yo he creado la password de aplicación en mi cuenta de gmail con autenticacion en 2 pasos y cuando pruebo mi sistema java desde mi pc localhost a través de eclipse funciona bien. Cuando lo transfiero al servidor de Hosting me da error de autenticacion, en mi local host tengo un tomcat 7 y algo. En el servidor remoto es tomcat 8.5

Responder

José Manuel Alarcón
José Manuel Alarcón

Habla con el hosting. Es bastante probable que el hosting no permita conexiones hacia el exterior a través de ciertos puertos. Averigua si te bloquean el puerto 587, y si te lo pueden desbloquear (lo dudo). Si no utiliza otro tipo de servicio de envío que admita puertos que no estén bloqueados en tu hosting (por ejemplo smtp2go o similar).

Saludos.

Responder

Marco Delgadillo
Marco Delgadillo

Buen dia, disculpas, pero tambien tengo un inconveniente: Hice una aplicacion sencilla en java con eclipse:

        String s_Rem = "[email protected]";
        String s_Pas = "pas16car";
        String s_Des = JT_Des.getText();
        String s_Ast =  JT_Asu.getText();
        String s_Msg = JA_Msg.getText();

        try {
          Properties Prpd = new Properties();
          Prpd.setProperty("mail.smtp.host", "smtp.gmail.com");
          Prpd.put("mail.smtp.user", s_Rem);
          Prpd.put("mail.smtp.clave", s_Pas);
          Prpd.put("mail.smtp.auth", "true");
          Prpd.put("mail.smtp.starttls.enable", "true");
          Prpd.put("mail.smtp.port", "587");

          Session sesion = Session.getDefaultInstance(Prpd);

          MimeMessage message = new MimeMessage(sesion);

          message.setFrom(new InternetAddress(s_Rem));
          message.addRecipient(Message.RecipientType.TO, new InternetAddress(s_Des));
          //message.addRecipient(Message.RecipientType.CC, new InternetAddress(s_Des));
          //message.addRecipient(Message.RecipientType.BCC, new InternetAddress(s_Des));
          message.setSubject(s_Ast);
          message.setText(s_Msg);

          Transport Trs = sesion.getTransport("smtp");
          Trs.connect("smtp.gmail.com",s_Rem, s_Pas);
          Trs.sendMessage(message, message.getAllRecipients());
          //Trs.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
          Trs.close();
          JOptionPane.showMessageDialog(null, "Correo Enviado a " + s_Des);

        } catch (MessagingException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
Complia y corre sin problemas, pero no se reciben los correos "enviados",  Ojala puedan decirme en que me estoy equivocando o que me falta, gracias y buen dia

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.