17 Programming Jakarta Mail with WebLogic Server

Learn how to program Jakarta Mail with WebLogic Server to add email capabilities to your WebLogic Server applications.

This chapter includes the following sections:

Overview of Using Jakarta Mail with WebLogic Server Applications

WebLogic Server includes the Jakarta Mail API version 1.5 reference implementation. Using the Jakarta Mail API, you can add email capabilities to your WebLogic Server applications. Jakarta Mail provides access from Java applications to Internet Message Access Protocol (IMAP)- and Simple Mail Transfer Protocol (SMTP)-capable mail servers on your network or the Internet. It does not provide mail server functionality; you must have access to a mail server to use Jakarta Mail.

Documentation for using the Jakarta Mail API is available at https://jakarta.ee/specifications/mail/1.6/. This section describes how you can use Jakarta Mail in the WebLogic Server environment.

The weblogic.jar file contains the following Jakarta Mail API packages:

  • jakarta.mail

  • jakarta.mail.event

  • jakarta.mail.internet

  • jakarta.mail.search

The weblogic.jar also contains the Java Activation Framework (JAF) package, which Jakarta Mail requires.

The jakarta.mail package includes providers for Internet Message Access protocol (IMAP) and Simple Mail Transfer Protocol (SMTP) mail servers. There is a separate POP3 provider for Jakarta Mail, which is not included in weblogic.jar. You can download the POP3 provider at https://maven.java.net/content/repositories/releases/com/sun/mail/pop3 and add it to the WebLogic Server classpath if you want to use it.

Understanding Jakarta Mail Configuration Files

Jakarta Mail depends on configuration files that define the mail transport capabilities of the system. The weblogic.jar file contains the standard configuration files which enable IMAP and SMTP mail servers for Jakarta Mail and define the default message types Jakarta Mail can process.

Jakarta Mail discovers transport/store providers from provider metadata and service-provider registration in the runtime. The supplied modules already register the protocols used in this chapter; ordinary use requires no provider-file edits. For an additional transport or store, supply a Jakarta Mail 2.1-compatible provider implementation and its documented provider registration, and make those resources visible to the application using the documented WebLogic classloading procedure. MIME content-handler extensions use Jakarta Activation registrations. Retain the server-provided Mail/Activation API types when adding an implementation.

See §§5.1 and 7.3 of Jakarta Mail 2.1 provider registry and content-type extension model

Configuring Jakarta Mail for WebLogic Server

To configure Jakarta Mail for use in WebLogic Server, you create a mail session in the WebLogic Remote Console. This allows server-side modules and applications to access Jakarta Mail services with JNDI, using session properties you preconfigure for them.

For example, by creating a mail session, you can designate the mail hosts, transport and store protocols, and the default mail user in the WebLogic Remote Console so that modules that use Jakarta Mail do not have to set these properties. A configured mail resource centralizes the properties and authentication used by applications through JNDI; it is a jakarta.mail.Session configuration object, not an open mail connection or a promise that every lookup returns the same Java object.

To use the WebLogic Remote Console to create a mail session, see Configure Access to JavaMail in the Oracle WebLogic Remote Console Online Help.

Configure the mail host’s required TLS and authentication settings before using the examples. For the SMTP STARTTLS example, set the following mail-session properties and replace the host placeholder with the actual mail-server name. STARTTLS must succeed before the example proceeds. If the server requires SMTP authentication, also set mail.smtp.auth=true and configure the mail-session username/password through the supported WebLogic mail-session credential fields.

mail.transport.protocol=smtp
mail.smtp.host=your-configured-smtp-host
mail.smtp.starttls.enable=true
mail.smtp.starttls.required=true
mail.smtp.ssl.checkserveridentity=true

The reader selects pop3s explicitly; replace the POP3 host placeholder and use the mail service’s configured TLS listener/port.

mail.store.protocol=pop3s
mail.pop3s.host=your-configured-pop3-host
mail.pop3s.ssl.checkserveridentity=true

Use the actual host name matching the server certificate and a trust configuration that validates its issuer. Retain certificate and hostname verification. The examples do not put credentials in source or URLs.

Use the looked-up Session directly when its configured properties and authentication are appropriate. Session.getInstance is a static factory for an independent Session; invoking it through a session variable does not inherit the original Session or its Authenticator. If an application requires independent configuration, copy the original properties into a new Properties object, apply the overrides, and create the new Session using Session.getInstance(properties, authenticator), supplying the required Authenticator explicitly. Copying properties alone does not copy the configured authenticator. Do not mutate the properties of a shared JNDI Session to customize one operation.

package examples.mail;

import java.util.Properties;
import jakarta.mail.Authenticator;
import jakarta.mail.Session;

public final class MailSessions {
    public static Session customize(Session configured, Properties overrides,
            Authenticator authenticator) {
        Properties properties = new Properties();
        properties.putAll(configured.getProperties());
        properties.putAll(overrides);
        return Session.getInstance(properties, authenticator);
    }
}

Sending Messages with Jakarta Mail

You can send a message using Jakarta Mail within a WebLogic Server module.

Here are the steps to send a message with Jakarta Mail:

Create and target a mail session whose JNDI name is myMailSession, or replace that literal with your configured name. Configure mail.from as an application-controlled sender authorized by the mail service, plus the SMTP host, TLS and any required authentication described in Configuring Jakarta Mail for WebLogic Server. Call send(to, subject, messageText) from your server-side code. Apply the application’s recipient authorization rules before this call; syntax validation is not authorization.Configuring Jakarta Mail for WebLogic Server

package examples.mail;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Multipart;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;

public final class SendMail {
    public static void send(String to, String subject, String messageText)
            throws NamingException, MessagingException {
        InitialContext naming = new InitialContext();
        try {
            Session session = (Session) naming.lookup("myMailSession");
            Transport.send(createMessage(session, to, subject, messageText));
        } finally {
            naming.close();
        }
    }

    public static MimeMessage createMessage(Session session, String to,
            String subject, String messageText) throws MessagingException {
        String from = session.getProperty("mail.from");
        if (from == null || from.isBlank()) {
            throw new MessagingException("Configure an application-controlled mail.from address");
        }
        requireSingleLine(from);
        requireSingleLine(to);
        requireSingleLine(subject);
        InternetAddress sender = new InternetAddress(from, true);
        sender.validate();
        InternetAddress[] recipients = InternetAddress.parse(to, true);
        if (recipients.length == 0) {
            throw new MessagingException("Specify at least one recipient");
        }
        for (InternetAddress recipient : recipients) {
            recipient.validate();
        }
        MimeMessage message = new MimeMessage(session);
        message.setFrom(sender);
        message.setRecipients(Message.RecipientType.TO, recipients);
        message.setSubject(subject, StandardCharsets.UTF_8.name());
        message.setSentDate(new Date());
        MimeBodyPart text = new MimeBodyPart();
        text.setText(messageText, StandardCharsets.UTF_8.name());
        Multipart content = new MimeMultipart();
        content.addBodyPart(text);
        message.setContent(content);
        return message;
    }

    private static void requireSingleLine(String value) throws MessagingException {
        if (value == null || value.indexOf('\r') >= 0 || value.indexOf('\n') >= 0) {
            throw new MessagingException("Address and subject values must be single-line text");
        }
    }
}

Transport.send submits the message to the configured transport; this does not guarantee delivery to the recipient’s inbox. The caller handles NamingException and MessagingException.

Validate user-provided contact addresses and use them as Reply-To only when required by the application; keep the configured, authorized sender. The example closes its naming context and retains the one-part multipart construction.

Reading Messages with Jakarta Mail

The Jakarta Mail API provides several options for reading messages, such as reading a specified message number or range of message numbers, or pre-fetching specific parts of messages into the folder's cache.

The Jakarta Mail API allows you to connect to a message store, which could be an IMAP server or POP3 server. Messages are stored in folders. With IMAP, message folders are stored on the mail server, including folders that contain incoming messages and folders that contain archived messages. With POP3, the server provides a folder that stores messages as they arrive. The POP3 provider exposes the remote mailbox as INBOX and retrieves message data as required. Reading does not automatically persist a local mailbox or remove messages from the server..

Folders are hierarchical structures, similar to disk directories. A folder can contain messages or other folders. The default folder is at the top of the structure. The special folder name INBOX refers to the primary folder for the user, and is within the default folder. To read incoming mail, you get the default folder from the store, and then get the INBOX folder from the default folder.

The API provides several options for reading messages. See the Jakarta Mail API for more information.

Here are steps to read incoming messages on a POP3 server from within a WebLogic Server module:

getStore("pop3s") explicitly selects POP3 TLS. Open the folder before retrieving messages and copy needed data while it is open because content may be fetched lazily. The example returns copied subject strings. Store is AutoCloseable; the folder uses explicit close(false), which does not request expunge.

This example uses the configured myMailSession resource and reads subject headers from INBOX over POP3 TLS. Replace the JNDI literal if needed. Supply mailHost, username and password through the application’s approved configuration/credential handling; no sample password is embedded. Configure the pop3s settings described below before invoking it.

package examples.mail;

import java.util.ArrayList;
import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import jakarta.mail.Folder;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Store;

public final class ReadMail {
    public static List<String> readSubjects(String mailHost, String username,
            String password) throws NamingException, MessagingException {
        InitialContext naming = new InitialContext();
        try {
            Session session = (Session) naming.lookup("myMailSession");
            try (Store store = session.getStore("pop3s")) {
                store.connect(mailHost, username, password);
                Folder inbox = store.getFolder("INBOX");
                inbox.open(Folder.READ_ONLY);
                try {
                    List<String> subjects = new ArrayList<>();
                    for (Message message : inbox.getMessages()) {
                        subjects.add(message.getSubject());
                    }
                    return subjects;
                } finally {
                    if (inbox.isOpen()) {
                        inbox.close(false);
                    }
                }
            }
        } finally {
            naming.close();
        }
    }
}

Reading messages from an IMAP server is similar to reading messages from a POP3 server. With IMAP, however, the Jakarta Mail API provides methods to create and manipulate folders and transfer messages between them. If you use an IMAP server, you can implement a full-featured, Web-based mail client with much less code than if you use a POP3 server. If the application needs local persistence or its own folder organization for POP3 messages, implement that storage explicitly or use a suitable local-store provider; the supplied POP3 provider does not create a persistent local message store. This chapter’s read-only example does not mark messages for deletion and closes without expunging them.