Send Emails with Java: A Simple Guide

Send an email in the internal application used for the notification system, e.g., monthly or weekly reports, an email with an attached file, or an email to an individual colleague with batch emails to subscribed clients.

The public application used for Registration Confirmation prevents invalid or nonexistent email addresses. Password Reset is used for users who forget their password and want to reset the password associated with their email.

Reports or Notifications

Scenario

The client wants reports monthly via email. The development team design generates reports as follows: process-generated reports in case of success or failure, and to create reports. The system will trigger the sending of an email process with information and the email format. If the generated report succeeds, the system will send an email with an attached file; otherwise, it will send a notification email that alerts the developer team and stakeholders to take care of the generated report failure.

Implement

The developer team created the process for sending an email with Jakarta Mail API libraries via SMTP so that the client receives monthly report information directly in their inbox.

Registration Confirmation

Scenario

Web applications allow users to create an account for any purpose.
The developer team must prevent invalid or nonexistent email addresses that require a confirmed email address. When the user registers, the system will send a confirmation email.

Implement

The developer team created a process to send an email with Jakarta Mail API libraries via SMTP so that users receive a confirmed email address.

Password Reset

Scenario

Web applications provide a password reset feature to support users who have forgotten their passwords. The email contains a link to change the password.

Implement

The development team has established a procedure for sending emails via SMTP, utilizing the Jakarta Mail API libraries. This process enables the transmission of a link to reset a password, which is dispatched to the email address associated with the user’s account registration.

Outlook

Outlook has made a significant change in how it sends emails. Instead of using the traditional SMTP (Simple Mail Transfer Protocol), Microsoft has shifted to using the Microsoft Graph API for sending emails.

Why the change?

  1. Security: Microsoft Graph supports more secure authentication methods like token-based authentication and conditional access policies.
  2. Deprecation of Basic Auth: Microsoft is phasing out Basic Authentication, which SMTP relies on.
  3. More Features: Graph allows not just sending emails but also accessing calendars, contacts, files, and more from Microsoft 365 — all in one unified API.

Example Gmail

public static void gmail() {
    final String username = "your_email@gmail.com";
    final String password = "password"; 
    //use password if disable two factor authentication.
    //use app password if enable two factor authentication.

    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"); //TLS

    // Create session with authentication
    Session session = Session.getInstance(props, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

    try {
        // Create message
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(username));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("recipient@gmail.com"));
        message.setSubject("Testing GmailSender");
        message.setText("Dear User,\n\nThis is a test email sent from GmailSender.");

        // Send message
        Transport.send(message);

        System.out.println("Email sent successfully.");

    } catch (MessagingException e) {
        throw new RuntimeException(e);
    }
}

If the application shows the error message “InvalidSecondFactor”, follow this instruction link. The developer needs to set the app password.

Google provides an API for accessing Gmail mailboxes and sending mail.

Example email with attached file

import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;

import java.io.IOException;
import java.util.Properties;

public static void gmail() {
    final String username = "your_email@gmail.com";
    final String password = "password";

    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"); //TLS

    // Create session with authentication
    Session session = Session.getInstance(props, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

    try {
        // Create message
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(username));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("recipient@gmail.com"));
        message.setSubject("Testing GmailSender");
        message.setText("Dear User,\n\nThis is a test email sent from GmailSender.");

        Multipart multipart = getMultipart();

        // Set the multipart message content
        message.setContent(multipart);

        // Send message
        Transport.send(message);

        System.out.println("Email sent successfully.");

    } catch (MessagingException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static Multipart getMultipart() throws MessagingException, IOException {
    String filePath = "monthly_report.pdf";

    // Create the message body part
    BodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setText("Please find the attached file.");

    // Create the attachment part
    MimeBodyPart attachmentPart = new MimeBodyPart();
    attachmentPart.attachFile(filePath);

    // Combine the message body and attachment
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);
    multipart.addBodyPart(attachmentPart);

    return multipart;
}

Example email with multiple attached files

import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
import java.io.IOException;
import java.util.Properties;

public static void gmail() {
    final String username = "your_email@gmail.com";
    final String password = "password";

    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"); //TLS

    // Create session with authentication
    Session session = Session.getInstance(props, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

    try {
        // Create message
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(username));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("recipient@gmail.com"));
        message.setRecipients(Message.RecipientType.CC,
                InternetAddress.parse("cc@gmail.com")); //Carbon Copy
        message.setRecipients(Message.RecipientType.BCC,
                InternetAddress.parse("bcc@gmail.com")); //Blind Carbon Copy
        message.setSubject("Testing GmailSender");
        message.setText("Dear User,\n\nThis is a test email sent from GmailSender.");

        Multipart multipart = getMultipart();

        // Set the multipart message content
        message.setContent(multipart);

        // Send message
        Transport.send(message);

        System.out.println("Email sent successfully.");

    } catch (MessagingException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static Multipart getMultipart() throws MessagingException, IOException {
    List<String> filePaths = new ArrayList<>(Arrays.asList("monthly_report.pdf", "weekly_report.pdf", "yearly_report.pdf"));

    // Create the message body part
    BodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setText("Please find the attached files.");

    // Create a multipart message
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    // Attach files
    for (String filePath : filePaths) {
        MimeBodyPart attachmentPart = new MimeBodyPart();
        attachmentPart.attachFile(filePath);
        multipart.addBodyPart(attachmentPart);
    }
    return multipart;
}

For example, send an email to multiple recipients

public static void gmail() {
    final String username = "your_email@gmail.com";
    final String password = "password"; 
    //use password if disable two factor authentication.
    //use app password if enable two factor authentication.
    String[] recipientEmails = {"recipient1@example.com", "recipient2@example.com", "recipient3@example.com"};

    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"); //TLS

    // Create session with authentication
    Session session = Session.getInstance(props, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

    try {
        // Create message
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(username));
        // Add multiple recipients
        for (String recipientEmail : recipientEmails) {
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipientEmail));
        }
        message.setSubject("Testing GmailSender");
        message.setText("Dear User,\n\nThis is a test email sent from GmailSender.");

        // Send message
        Transport.send(message);

        System.out.println("Email sent successfully.");

    } catch (MessagingException e) {
        throw new RuntimeException(e);
    }
}

For example, send an email with an attached file and encode it in Base64.

The developer is facing a problem when sending an email with an attachment, but the email hasn’t been sent for an unknown reason.
The developer can assume the file contains an invalid or forbidden character, such as an image or text file. When sending through HTTP, use Base64 Encoding to solve this problem.

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.*;
import java.nio.file.Files;
import java.util.Base64;
import java.util.Properties;


public class EmailWithBase64Attachment {
    public static void main(String[] args) {
        final String username = "example@example.com";
        final String password = "password";

        // SMTP server properties for Hotmail
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", "smtp-mail.outlook.com");
        props.put("mail.smtp.port", "587");

        // Create session with authentication
        Session session = Session.getInstance(props, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });


        try {
            // Create message
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(username));
            // Add multiple recipients
            String[] recipientEmails = {"recipient1@example.com"};
            for (String recipientEmail : recipientEmails) {
                message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipientEmail));
            }
            message.setSubject("Subject of the Email");

            // Create the message part
            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setText("This is the message body with an attachment.");

            // Create a multipart object
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messageBodyPart);

            // Add the attachment part
            BodyPart attachmentPart = new MimeBodyPart();
            File file = new File("/path_to_file/image.png"); // Path to the file
            String base64EncodedFile = encodeFileToBase64(file);
            DataSource source = new ByteArrayDataSource(base64EncodedFile, "application/octet-stream");
            attachmentPart.setDataHandler(new DataHandler(source));
            attachmentPart.setFileName(file.getName());
            multipart.addBodyPart(attachmentPart);

            // Set the multipart content to the message
            message.setContent(multipart);

            // Send the message
            Transport.send(message);
            System.out.println("Email sent successfully with Base64 encoded attachment.");
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

    // Encode file to Base64
    public static String encodeFileToBase64(File file) {
        try {
            byte[] fileContent = Files.readAllBytes(file.toPath());
            return Base64.getEncoder().encodeToString(fileContent);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    // ByteArrayDataSource class to handle Base64 encoded data
    static class ByteArrayDataSource implements DataSource {
        private byte[] data;
        private String type;

        public ByteArrayDataSource(String data, String type) {
            this.data = Base64.getDecoder().decode(data);
            this.type = type;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(data);
        }

        @Override
        public OutputStream getOutputStream() throws IOException {
            throw new IOException("Not supported");
        }

        @Override
        public String getContentType() {
            return type;
        }

        @Override
        public String getName() {
            return "ByteArrayDataSource";
        }
    }
}

Output.

Email sent successfully with Base64 encoded attachment.

Example subject and HTML encoding UTF-8

public static void outlook(){
    final String username = "your_email@outlook.com";
    final String password = "password";

    // SMTP server properties for Hotmail
    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", "smtp-mail.outlook.com");
    props.put("mail.smtp.port", "587");

    // Create session with authentication
    Session session = Session.getInstance(props, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
        }
    });

    try {

        // Create message
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress(username));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("recipient@outlook.com"));

        // Set UTF-8 encoded subject
        String subject = "Subject with UTF-8 Characters: こんにちは";
        message.setSubject(subject, "UTF-8");

        String htmlBody = "<html><body><p>Hello, this is an HTML email with UTF-8 characters: こんにちは</p></body></html>";
        
        // Create the HTML body part
        BodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setContent(htmlBody, "text/html; charset=utf-8");

        // Create a multipart message
        Multipart multipart = new MimeMultipart();
        multipart.addBodyPart(messageBodyPart);

        // Set the multipart message content
        message.setContent(multipart);

        // Send message
        Transport.send(message);

        System.out.println("Email sent successfully.");

    } catch (MessagingException e) {
        throw new RuntimeException(e);
    }
}

Finally

Email sending can be integrated with the Quartz scheduler library or message queue to improve application design, which can trigger the send email process.

Leave a Comment

Your email address will not be published. Required fields are marked *