All Products
Search
Document Center

Direct Mail:SMTP Java call example

Last Updated:May 27, 2026

This topic shows how to send emails through Simple Mail Transfer Protocol (SMTP) using the JavaMail API.

Add the following dependencies to your Maven pom.xml:

<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>

Connection parameters

Configure the following values before running the sample code:

Parameter

Value

Notes

SMTP server

smtpdm.aliyun.com

Direct Mail SMTP endpoint

Port 80 or 25

No encryption

Default. Use when port 465 is blocked.

Port 465

SSL/TLS

Requires SSLSocketFactory configuration (see commented-out lines in the sample).

Username

Your sender address

The sender address created in the Direct Mail console.

Password

SMTP password

Set when creating the sender address in the console.

Sample code

Warning

Never hard-code credentials in source code or commit them to version control. In production, load USER_NAME and PASSWORD from environment variables or a secrets manager.

The sample below uses the JavaMail MimeMessage API to authenticate with Direct Mail's SMTP server, compose an email with HTML content, and call Transport.send(). Commented-out sections show optional features: plain text, attachments, SSL, and email tracking.

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 = "Sender Address";
    private static final String PASSWORD = "xxxxxxx";

    protected static String genMessageID(String mailFrom) {
        // Generate 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 the environment properties for sending emails
        final Properties props = new Properties();

        // To send emails over SMTP, identity verification is required
        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". If you use SSL, remove the configuration for port 80 or 25 and use the following configuration:
        //Encryption method:
        //props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        //props.put("mail.smtp.socketFactory.fallback", "false");// Disable 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 mailfrom parameter
        props.put("mail.user", USER_NAME);// The sender's account (the sender address created in the console)
        props.put("mail.password", PASSWORD);// The SMTP password for the sender address (set the password for the sender address in the console)
        //props.put("mail.smtp.connectiontimeout", 1000);
        System.setProperty("mail.mime.splitlongparameters", "false");// This resolves display issues caused by excessively long attachment names
        //props.setProperty("mail.smtp.ssl.enable", "true");  // Use this with port 465

        // Build the authorization information for SMTP identity verification
        Authenticator authenticator = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(USER_NAME, PASSWORD);
            }
        };

        //Create an email session using the environment properties and authorization information
        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 email address and name. Use the sender address configured in the console. This must be the same as mail.user above. You can customize the name.
            InternetAddress from = new InternetAddress(USER_NAME, "Sender Nickname");// The from parameter. This can be used for relaying. Note: Relayed emails are more likely to be rejected by recipients or moved to the spam folder.
            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("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/text;charset=UTF-8");// Plain text content. This will be overwritten if you use MimeBodyPart.
//            or
//            message.setContent("Test<br> HTML content 2", "text/html;charset=UTF-8");// HTML content. This will be overwritten if you use MimeBodyPart.

//            // To enable the email tracking service, use the following code to set the tracking link header. For prerequisites and constraints, see the "How to enable the data tracking feature?" document.
//            String tagName = "tagname4";
//            HashMap<String, String> trace = new HashMap<>();
//            // This is the string "1"
//            trace.put("OpenTrace", "1");      // Enable email open tracking
//            trace.put("LinkTrace", "1");     // Enable URL click tracking in the email
//            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 link header
//            message.addHeader("X-AliDM-Trace", base64Trace);
            // Example value in the original email (EML): X-AliDM-Trace: eyJUYWdOYW1lIjoiVGVzdCIsIk9wZW5UcmFjZSI6IjEiLCJMaW5rVHJhY2UiOiIxIn0=

            // Send attachments and content:
            // 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 will overwrite the previous message.setContent.
            multipart.addBodyPart(htmlPart);

//            // Attachment part
//            // Send attachments. The total email size cannot exceed 15 MB. Create a message part.
//            // 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));
//                // This handles garbled characters in Chinese attachment names (including file paths)
//                mimeBodyPart.setFileName(MimeUtility.encodeWord(fileDataSource.getName()));
//                mimeBodyPart.addHeader("Content-Transfer-Encoding", "base64");
//                multipart.addBodyPart(mimeBodyPart);
//            }

//            // Send URL attachments
//            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);
//                }
//            }

            // Add the complete message
            message.setContent(multipart);
            // End of the code for sending attachments

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

    }

}

Custom SMTP headers

Use the following custom headers to enable email tracking and tagging. Pass these headers as Base64-encoded JSON via message.addHeader(). For prerequisites and configuration steps, see the email tracking documentation.

Header

Key

Value

Description

X-AliDM-Trace

OpenTrace

"1"

Tracks email open events.

X-AliDM-Trace

LinkTrace

"1"

Tracks URL clicks in the email body.

X-AliDM-Trace

TagName

Your email tag name

Associates the message with an email tag created in the console.

The commented-out tracking block in the sample code builds a JSON object with these keys, Base64-encodes it, and sets it as the X-AliDM-Trace header. The resulting EML header looks like:

X-AliDM-Trace: eyJUYWdOYW1lIjoiVGVzdCIsIk9wZW5UcmFjZSI6IjEiLCJMaW5rVHJhY2UiOiIxIn0=

FAQ

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

This happens when the SMTP request lists multiple addresses in the message header. Choose an approach based on your use case:

  • Shared thread (all recipients visible): Send one request with multiple To and CC addresses. All recipients can see each other, and the Message-ID is the same for everyone. This suits scenarios where all recipients are part of the same conversation. You can also omit To and CC and use BCC only, but this is not recommended — some recipients' anti-spam policies may reject BCC-only messages. For the maximum number of recipients per request, see Limits.

  • Individual delivery (recipients hidden from each other): Send one request per recipient. Each request produces a separate email with a usually different Message-ID, so no recipient sees the others. For example, sending to six people requires six requests. SMTP supports concurrent requests, so you can parallelize these calls.