Java code example for SMTP

Updated at:

This topic explains how to use JavaMail to send emails over SMTP.

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

Sample code

package org.example;

import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
//import java.net.MalformedURLException;
import java.util.Date;
import java.util.Properties;
import java.util.UUID;
//import java.util.HashMap;
//import java.util.Base64;
//import java.net.URL;
//import java.io.IOException;
//import java.io.InputStream;
//import javax.mail.util.ByteArrayDataSource;
//import java.net.URLEncoder;
//import javax.activation.DataHandler;
//import javax.activation.FileDataSource;
//import javax.activation.URLDataSource;

//import com.google.gson.GsonBuilder;

public class SampleMail {
    // Configure constants.
    private static final String SMTP_HOST = "smtpdm.aliyun.com";
    private static final int SMTP_PORT = 80;
    private static final String USER_NAME = "your_sender_address";
    private static final String PASSWORD = "your_smtp_password";

    protected static String genMessageID(String mailFrom) {
        // Generate the Message-ID.
        if (!mailFrom.contains("@")) {
            throw new IllegalArgumentException("Invalid email format: " + mailFrom);
        }
        String domain = mailFrom.split("@")[1];
        UUID uuid = UUID.randomUUID();
        return "<" + uuid.toString() + "@" + domain + ">";
    }

    private static void setRecipients(MimeMessage message, Message.RecipientType type, String[] recipients)
            throws MessagingException {
        // Set recipient addresses.
        if (recipients == null || recipients.length == 0) {
            return; // Do not set if the list is empty.
        }
        InternetAddress[] addresses = new InternetAddress[recipients.length];
        for (int h = 0; h < recipients.length; h++) {
            addresses[h] = new InternetAddress(recipients[h]);
        }
        message.setRecipients(type, addresses);
    }

    public static void main(String[] args) throws MessagingException, UnsupportedEncodingException {
        // Configure email sending properties.
        final Properties props = new Properties();

        // Enable SMTP authentication.
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.host", SMTP_HOST);
        // Set the port:
        props.put("mail.smtp.port", SMTP_PORT);// or "25". For SSL, remove the port 80/25 configuration and use the following settings instead:
        // Encryption method:
        //props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        //props.put("mail.smtp.socketFactory.fallback", "false");// Prevents fallback to non-encrypted connections.
        //props.put("mail.smtp.socketFactory.port", "465");
        //props.put("mail.smtp.port", "465");

        props.put("mail.smtp.from", USER_NAME);    // The mail.from parameter.
        props.put("mail.user", USER_NAME);// The sender account (the sender address created in the console).
        props.put("mail.password", PASSWORD);// The SMTP password for the sender address (set in the console).
        //props.put("mail.smtp.connectiontimeout", 1000);
        System.setProperty("mail.mime.splitlongparameters", "false");// Prevents display issues caused by excessively long attachment filenames.
        //props.put("mail.smtp.ssl.enable", "true");  // Use with port 465.
        //props.put("mail.smtp.ssl.protocols", "TLSv1.2");  // Specify the TLS version.

        // Create the authenticator for SMTP authentication.
        Authenticator authenticator = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(USER_NAME, PASSWORD);
            }
        };

        // Create a mail session using the properties and authenticator.
        Session mailSession = Session.getInstance(props, authenticator);

        String messageIDValue = genMessageID(USER_NAME);
        MimeMessage message = new MimeMessage(mailSession) {
            @Override
            protected void updateMessageID() throws MessagingException {
                setHeader("Message-ID", messageIDValue);
            }
        };

        try {
            // Set the sender's address and alias. The address must be configured in the console and match the 'mail.user' property. The alias is a custom display name.
            InternetAddress from = new InternetAddress(USER_NAME, "Your Sender Alias");
            message.setFrom(from);

            setRecipients(message, Message.RecipientType.TO, new String[]{"recipient_address_1", "recipient_address_2"});
            setRecipients(message, Message.RecipientType.CC, new String[]{"recipient_address_3", "recipient_address_4"});
            setRecipients(message, Message.RecipientType.BCC, new String[]{"recipient_address_5", "recipient_address_6"});

            InternetAddress replyToAddress = new InternetAddress("your_reply_to_address");
            message.setReplyTo(new Address[]{replyToAddress});// Optional. Set the reply-to address.
            message.setSentDate(new Date());
            message.setSubject("Test subject");
//            message.setContent("Test txt content 1", "text/plain;charset=UTF-8");// Plain text content. This is overwritten if you use MimeBodyPart.
//            or
//            message.setContent("Test<br> HTML content 2", "text/html;charset=UTF-8");// HTML content. This is overwritten if you use MimeBodyPart.

//            // To enable email tracking, set the X-AliDM-Trace header as shown below. For prerequisites and constraints, see the documentation on enabling data tracking.
//            String tagName = "your_tag_name";
//            HashMap<String, String> trace = new HashMap<>();
//            trace.put("OpenTrace", "1");      // Enable open tracking.
//            trace.put("LinkTrace", "1");     // Enable URL click tracking.
//            trace.put("TagName", tagName);   // The tag name created in the console.
//            String jsonTrace = new GsonBuilder().setPrettyPrinting().create().toJson(trace);
//            //System.out.println(jsonTrace);
//            String base64Trace = new String(Base64.getEncoder().encode(jsonTrace.getBytes()));
//            // Set the tracking header.
//            message.addHeader("X-AliDM-Trace", base64Trace);
            // Example value in the raw email (EML): X-AliDM-Trace: eyJUYWdOYW1lIjoiVGVzdCIsIk9wZW5UcmFjZSI6IjEiLCJMaW5rVHJhY2UiOiIxIn0=

            // Add content and attachments:
            // Create a multipart message.
            Multipart multipart = new MimeMultipart();

//            // Create a BodyPart for plain text content.
//            BodyPart textPart = new MimeBodyPart();
//            textPart.setText("Test txt content 3");
//            multipart.addBodyPart(textPart);

            // Create a BodyPart for HTML content.
            BodyPart htmlPart = new MimeBodyPart();
            htmlPart.setContent("Test<br> HTML content 4", "text/html;charset=UTF-8");// Set the email content. This overwrites the previous message.setContent call.
            multipart.addBodyPart(htmlPart);

//            // Add attachments.
//            // Create and add attachment parts. The total email size, including attachments, cannot exceed 15 MB.
//            // Send local attachments.
//            String[] fileList = {"C:\\Users\\Downloads\\test1.txt", "C:\\Users\\Downloads\\test2.txt"};
//            for (String filePath : fileList) {
//                MimeBodyPart mimeBodyPart = new MimeBodyPart();
//
//                FileDataSource fileDataSource = new FileDataSource(filePath);
//                mimeBodyPart.setDataHandler(new DataHandler(fileDataSource));
//                // Encode the attachment filename to prevent garbled characters.
//                mimeBodyPart.setFileName(MimeUtility.encodeWord(fileDataSource.getName()));
//                mimeBodyPart.addHeader("Content-Transfer-Encoding", "base64");
//                multipart.addBodyPart(mimeBodyPart);
//            }


//            // Send attachments from a URL.
//            String[] fileListUrl = {"https://example.oss-cn-shanghai.aliyuncs.com/xxxxxxxxxxx1.png", "https://example.oss-cn-shanghai.aliyuncs.com/xxxxxxxxxxx2.png"};
//            for (String fileUrl : fileListUrl) {
//                URL url = new URL(fileUrl);
//                String filename = url.getPath();
//                filename = filename.substring(filename.lastIndexOf('/') + 1);
//                try (InputStream in = url.openStream()) {
//                    // Create an attachment part.
//                    MimeBodyPart attachmentPart = new MimeBodyPart();
//                    // Use a byte array data source.
//                    ByteArrayDataSource ds = new ByteArrayDataSource(in, "application/octet-stream");
//                    attachmentPart.setDataHandler(new javax.activation.DataHandler(ds));
//                    attachmentPart.setFileName(filename);
//                    attachmentPart.setDisposition(MimeBodyPart.ATTACHMENT);
//                    multipart.addBodyPart(attachmentPart);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            }

            // Set the multipart content for the message.
            message.setContent(multipart);
            // End of the code for sending attachments.

            //mailSession.setDebug(true);// Enable debug mode.
            Transport.send(message);
            System.out.println("Email sent successfully!");
        } catch (MessagingException | UnsupportedEncodingException e) {
            System.err.println("Failed to send the email: " + e.getMessage());
            e.printStackTrace();
//        } catch (MalformedURLException e) {
//            throw new RuntimeException(e);
        }

    }

}

FAQ

Why do I see other recipients in the email I received?

This can happen if the SMTP request includes other recipients in the email headers.

  • SMTP allows you to send an email to multiple recipients in a single request. For specific limits, see quotas (number of recipients per call). However, this method displays all recipients in the email headers. This approach is suitable for scenarios where multiple people are part of the same email conversation. The Message-ID is typically the same for all recipients. Alternatively, you can omit the TO and CC fields and only use the BCC field. However, this is not recommended as the email may be rejected by the recipient's anti-spam policy.

  • If you want each recipient to receive the email individually without seeing other recipients, you must send a separate request for each one. For example, sending an email to six people requires six separate requests. SMTP supports concurrent requests. Each request is treated as a separate email, and the Message-ID is typically different for each one.