Maik
Maik

Reputation: 891

Send email with gmail using java

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 = "[email protected]";

    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?

Upvotes: 5

Views: 10015

Answers (3)

Kuntal Ghosh
Kuntal Ghosh

Reputation: 3698

First of all, you cannot use password while sending email via Gmail. You need to generate app-specific password for this.

To enable app-specific password follow below steps.

Step 1: Enable 2FA. To enable 2FA, please click here.

Step 2: Create an app-specific password. To create one, please click here.

Click on the highlighted option from the "Select app" dropdown. Click Generate. It will generate 16 digits password and appear only once. Copy somewhere for future use.

enter image description here

In application.properties file add below lines for email configurations

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=YOUR GMAIL ID
spring.mail.password=APP-SPECIFIC PASSWORD
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

The maven dependency can also be added by modifying your project’s pom.xml file to include the following

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

If you need HTML email, you can use MimeMessage class for this purpose.

The service file to send the email is as following. This will create HTML emails for you.

package com.comp.service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import com.comp.serviceIntf.EmailService;

@Service
public class EmailServiceImpl implements EmailService {

    @Autowired
    private JavaMailSender mailSender;
    
    @Override
    public void sendEmail(String to, String name, String userid, String password) throws MessagingException
    {
        String htmlContent = "Hi %s, <br /><br />Welcome to <b>MyCompany</b>. <br />Your UserID is: <b>%s</b> and Password is: <b>%s</b><br /><h5>This is system generated password. You can change it anytime after login.</h5><h5>Please do not share this credential with anybody else.</h5><br />With regards,<br />MyCompany";
        htmlContent = String.format(htmlContent, name, userid, password);
        
        String subject = "Welcome %s (%s) on successful registration";
        subject = String.format(subject, name, userid);
        
        
        MimeMessage message = mailSender.createMimeMessage();
        message.setRecipients(MimeMessage.RecipientType.TO, to);
        message.setSubject(subject);
        message.setContent(htmlContent, "text/html; charset=utf-8");
        mailSender.send(message);
    }
}

If you do not need HTML email, you can use SimpleMailMessage class for this purpose.

SimpleMailMessage message = new SimpleMailMessage();
message.setTo(to);
message.setSubject(subject);
message.setText(body);

mailSender.send(message);

Note: I am unaware of any other email like yahoo, outlook etc. This discussion is purely from Gmail point of view.

Upvotes: 4

hidden_machine
hidden_machine

Reputation: 191

    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)

Upvotes: 6

Adriaan Koster
Adriaan Koster

Reputation: 16209

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("[email protected]"));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email));
        message.setSubject(subject);
        message.setText(body);
        return message;
    }
}

Upvotes: 0

Related Questions