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 |
|
Direct Mail SMTP endpoint |
|
Port 80 or 25 |
No encryption |
Default. Use when port 465 is blocked. |
|
Port 465 |
SSL/TLS |
Requires |
|
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
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 |
|
|
|
|
Tracks email open events. |
|
|
|
|
Tracks URL clicks in the email body. |
|
|
|
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=