2

As title says, I would like to send emails with my gmail account writing some java code. I have found many code examples, but none of them is working for me

I was looking a this one: How can I send an email by Java application using GMail, Yahoo, or Hotmail?

I have tried the code posted as answer, but I get this exception:

javax.mail.MessagingException: Can't send command to SMTP host;
  nested exception is:
    javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
    at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:1717)
    at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:1704)
    at com.sun.mail.smtp.SMTPTransport.ehlo(SMTPTransport.java:1088)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:468)
    at javax.mail.Service.connect(Service.java:291)
    at javax.mail.Service.connect(Service.java:172)
...

The code is this:

public class GmailTest {
   
    private static String USER_NAME = "*****";  // GMail user name (just the part before "@gmail.com")
    private static String PASSWORD = "********"; // GMail password
    private static String RECIPIENT = "random.address@gmail.com";

    public static void main(String[] args) {
        String from = USER_NAME;
        String pass = PASSWORD;
        String[] to = { RECIPIENT }; // list of recipient email addresses
        String subject = "Java send mail example";
        String body = "Welcome to JavaMail!";

        sendFromGMail(from, pass, to, subject, body);
    }

    private static void sendFromGMail(String from, String pass, String[] to, String subject, String body) {
        Properties props = System.getProperties();
        String host = "smtp.gmail.com";
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.user", from);
        props.put("mail.smtp.password", pass);
        props.put("mail.smtp.port", "587");
        props.put("mail.smtp.auth", "true");

        Session session = Session.getDefaultInstance(props);
        MimeMessage message = new MimeMessage(session);

        try {
            message.setFrom(new InternetAddress(from));
            InternetAddress[] toAddress = new InternetAddress[to.length];

            // To get the array of addresses
            for( int i = 0; i < to.length; i++ ) {
                toAddress[i] = new InternetAddress(to[i]);
            }

            for( int i = 0; i < toAddress.length; i++) {
                message.addRecipient(Message.RecipientType.TO, toAddress[i]);
            }

            message.setSubject(subject);
            message.setText(body);
            Transport transport = session.getTransport("smtp");
            transport.connect(host, from, pass);
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
        
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Should this work in 2022 or did something change? Why am I getting that exception?

Maik
  • 811
  • 3
  • 22
  • 35

2 Answers2

4
    public class EmailService {

    private String username;
    private String password;

    private final Properties prop;
public EmailService(String host, int port, String username, String password) {
            prop = new Properties();
            prop.put("mail.smtp.auth", true);
            prop.put("mail.smtp.starttls.enable", "true");
            prop.put("mail.smtp.host", host);
            prop.put("mail.smtp.port", port);
            prop.put("mail.smtp.ssl.trust", host);
    
            this.username = username;
            this.password = password;
        }
    
        public void sendMail(String from,String to,String subject, String msg) throws Exception {
    
            Session session = Session.getInstance(prop, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });
    
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject(subject);
    
            MimeBodyPart mimeBodyPart = new MimeBodyPart();
            mimeBodyPart.setContent(msg, "text/html; charset=utf-8");
    
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(mimeBodyPart);
    
            message.setContent(multipart);
    
            Transport.send(message);
}
        }

and then call the function like so:

new EmailService("smtp.gmail.com", 587, "<emailID>", "<pass(not the actual gmail-account password if you're using gmail for this>")
                    .sendMail("<emailID>",
                            toemail,
                            "<title>",
                            "<body>);

However, that's only half the solution. Since they discontinued the Less Secure App Access feature on gmail accounts, you should access your gmail account through a different way now.

You must enable 2FA on that gmail account, and add an entry to App passwords under your google account. After that, the password you provide in the above function would be the 'App password' that you got from the gmail account(not the actual gmail account password, this one is auto-generated I believe).

enter image description here

I am unaware of any other email service that offers smtp email feature for free nowadays. They all require you to pay in someway,except for gmail(Correct me if I'm wrong)

  • Ok I have enabled the 2FA on the gmail account, and created an app password (for a Windows Computer). Now when i try to run your code, at the line Transport.send(message); i get the following exception: javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) – Maik Nov 18 '22 at 13:06
  • @Maik Try to first send the email through curl, if it works through curl, then the issue is definitely either jdk version or the email library version related. If it doesn't work through curl, then the issue is probably incorrect authentication – hidden_machine Nov 18 '22 at 17:26
  • @Maik [Here](https://stackoverflow.com/a/16069786/16348170) is a simple one line command to send email through curl – hidden_machine Nov 18 '22 at 17:28
  • I didn't know what curl is, I'm learning... The example you linked is for linux, but I guess it should work on a windows machine too, right? I get this error: "curl: (3) URL using bad/illegal format or missing URL". The right port to use is 465 or 587? – Maik Nov 21 '22 at 11:12
  • @Maik , just remove the backslashes, and it should work. The backslashes are used for spanning the command across multiple lines in a `linux` terminal. The equivalent would be `^` in `windows` – hidden_machine Nov 21 '22 at 16:07
  • @Maik gmail provides an an official guide to use their services; on their website ; https://developers.google.com/gmail/api/quickstart/java https://developers.google.com/gmail/api/guides/sending – hidden_machine Nov 22 '22 at 20:05
  • I already had written the command without backslashes, and the one above was the error i got. I tried again, removing single quote from the various parameters, and this time I got "252 2.1.5 Send some mail, I'll try my best p35-20020a056402502300b00463b9d47e1fsm6033215eda.71 - gsmtp". But nothing happens: I got no mail and the is no message in the sent box – Maik Nov 29 '22 at 10:12
0

I figured this out a while back and this should work:

import javax.mail.*;

public class Emailer {

    private final String username;
    private final String password;
    private Session session;  

    public Emailer(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void send(String email, String subject, String content) {
        if (hasSession()) {
            try {
                Transport.send(createMimeMessage(email, session, subject, content));
                System.out.printf("Email sent to %s%n", email);
            } catch (MessagingException e) {
                e.printStackTrace();
            }
        }
    }

    private boolean hasSession() {
        if (session == null) {
            session = startSessionTLS();
        }
        if (session == null) {
            System.out.printf("Cannot start email session%n");
            return false;
        }
        return true;
    }

    private Session startSessionTLS() {

        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "587");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");

        return Session.getInstance(props, new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
    }

    private MimeMessage createMimeMessage(String email, Session session, String subject, String body) throws MessagingException {
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress("noreply@email.com"));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email));
        message.setSubject(subject);
        message.setText(body);
        return message;
    }
}
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60