CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-jakarta-mail--jakarta-mail-api

Jakarta Mail defines a platform-independent and protocol-independent framework to build mail and messaging applications.

Pending
Overview
Eval results
Files

store-folder-management.mddocs/

Store and Folder Management

Store and folder management provides comprehensive capabilities for accessing mail stores, managing folders, and organizing messages within mailboxes.

Store Operations

The Store abstract class provides access to message repositories such as IMAP servers, POP3 servers, or local mailboxes.

public abstract class Store extends Service {
    // Folder access
    public abstract Folder getDefaultFolder() throws MessagingException;
    public abstract Folder getFolder(String name) throws MessagingException;
    public abstract Folder getFolder(URLName url) throws MessagingException;
    
    // Event handling
    public void addStoreListener(StoreListener l);
    public void removeStoreListener(StoreListener l);
    
    // Store information
    public Folder[] getPersonalNamespaces() throws MessagingException;
    public Folder[] getUserNamespaces(String user) throws MessagingException;
    public Folder[] getSharedNamespaces() throws MessagingException;
}

Store Usage Example

import jakarta.mail.*;
import java.util.Properties;

// Configure properties for IMAP store
Properties props = new Properties();
props.put("mail.store.protocol", "imaps");
props.put("mail.imaps.host", "imap.gmail.com");
props.put("mail.imaps.port", "993");
props.put("mail.imaps.ssl.enable", "true");

Session session = Session.getInstance(props);

// Connect to store
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "username@gmail.com", "password");

try {
    // Get default folder (usually root)
    Folder defaultFolder = store.getDefaultFolder();
    System.out.println("Default folder: " + defaultFolder.getFullName());
    
    // Get inbox
    Folder inbox = store.getFolder("INBOX");
    
    // List all folders
    Folder[] folders = defaultFolder.list("*");
    for (Folder folder : folders) {
        System.out.println("Folder: " + folder.getFullName());
    }
} finally {
    store.close();
}

Folder Operations

The Folder abstract class represents a container for messages and provides comprehensive folder management capabilities.

public abstract class Folder implements AutoCloseable {
    // Folder constants
    public static final int HOLDS_MESSAGES = 0x01;
    public static final int HOLDS_FOLDERS = 0x02;
    public static final int READ_ONLY = 1;
    public static final int READ_WRITE = 2;
    
    // Basic folder properties
    public abstract String getName();
    public abstract String getFullName();
    public abstract Folder getParent() throws MessagingException;
    public abstract int getType() throws MessagingException;
    public abstract boolean exists() throws MessagingException;
    
    // Folder operations
    public abstract boolean create(int type) throws MessagingException;
    public abstract boolean delete(boolean recurse) throws MessagingException;
    public abstract boolean renameTo(Folder f) throws MessagingException;
    
    // Folder access
    public abstract void open(int mode) throws MessagingException;
    public abstract void close(boolean expunge) throws MessagingException;
    public abstract boolean isOpen();
    public int getMode();
    
    // Message access
    public abstract int getMessageCount() throws MessagingException;
    public abstract Message getMessage(int msgnum) throws MessagingException;
    public abstract Message[] getMessages() throws MessagingException;
    public abstract Message[] getMessages(int start, int end) throws MessagingException;
    public abstract Message[] getMessages(int[] msgnums) throws MessagingException;
    
    // New/unread message counts
    public int getNewMessageCount() throws MessagingException;
    public int getUnreadMessageCount() throws MessagingException;
    public int getDeletedMessageCount() throws MessagingException;
    
    // Message operations
    public abstract void appendMessages(Message[] msgs) throws MessagingException;
    public abstract Message[] expunge() throws MessagingException;
    public abstract Message[] search(SearchTerm term) throws MessagingException;
    public abstract Message[] search(SearchTerm term, Message[] msgs) throws MessagingException;
    
    // Folder hierarchy
    public abstract Folder[] list() throws MessagingException;
    public abstract Folder[] list(String pattern) throws MessagingException;
    public abstract Folder[] listSubscribed() throws MessagingException;
    public abstract Folder[] listSubscribed(String pattern) throws MessagingException;
    
    // Subscription management
    public abstract boolean isSubscribed() throws MessagingException;
    public abstract void setSubscribed(boolean subscribe) throws MessagingException;
    
    // Event handling
    public void addConnectionListener(ConnectionListener l);
    public void removeConnectionListener(ConnectionListener l);
    public void addFolderListener(FolderListener l);
    public void removeFolderListener(FolderListener l);
    public void addMessageChangedListener(MessageChangedListener l);
    public void removeMessageChangedListener(MessageChangedListener l);
    public void addMessageCountListener(MessageCountListener l);
    public void removeMessageCountListener(MessageCountListener l);
    
    // Store reference
    public Store getStore();
    
    // String representation
    public String toString();
}

Folder Usage Example

import jakarta.mail.*;
import jakarta.mail.search.*;

// Open inbox for reading
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);

try {
    // Get folder information
    System.out.println("Folder name: " + inbox.getName());
    System.out.println("Full name: " + inbox.getFullName());
    System.out.println("Message count: " + inbox.getMessageCount());
    System.out.println("New messages: " + inbox.getNewMessageCount());
    System.out.println("Unread messages: " + inbox.getUnreadMessageCount());
    
    // Check folder capabilities
    if ((inbox.getType() & Folder.HOLDS_MESSAGES) != 0) {
        System.out.println("Folder can hold messages");
    }
    if ((inbox.getType() & Folder.HOLDS_FOLDERS) != 0) {
        System.out.println("Folder can hold subfolders");
    }
    
    // Get all messages
    Message[] messages = inbox.getMessages();
    
    // Get recent messages only
    Message[] recentMessages = inbox.search(new FlagTerm(new Flags(Flags.Flag.RECENT), true));
    
    // Get messages from specific range
    if (messages.length > 10) {
        Message[] lastTen = inbox.getMessages(messages.length - 9, messages.length);
    }
    
} finally {
    inbox.close(false); // Don't expunge on close
}

Folder Management Operations

Creating and Managing Folders

// Create new folder
Folder newFolder = store.getFolder("Archive");
if (!newFolder.exists()) {
    boolean created = newFolder.create(Folder.HOLDS_MESSAGES);
    if (created) {
        System.out.println("Folder created successfully");
    }
}

// Create folder hierarchy
Folder projectFolder = store.getFolder("Projects");
if (!projectFolder.exists()) {
    projectFolder.create(Folder.HOLDS_FOLDERS);
}

Folder subFolder = store.getFolder("Projects/Project1");
if (!subFolder.exists()) {
    subFolder.create(Folder.HOLDS_MESSAGES);
}

// Rename folder
Folder oldFolder = store.getFolder("OldName");
Folder newFolderName = store.getFolder("NewName");
if (oldFolder.exists()) {
    boolean renamed = oldFolder.renameTo(newFolderName);
    if (renamed) {
        System.out.println("Folder renamed successfully");
    }
}

// Delete folder
Folder folderToDelete = store.getFolder("Temporary");
if (folderToDelete.exists()) {
    // Close if open
    if (folderToDelete.isOpen()) {
        folderToDelete.close(false);
    }
    
    boolean deleted = folderToDelete.delete(false); // Don't delete recursively
    if (deleted) {
        System.out.println("Folder deleted successfully");
    }
}

Folder Hierarchy Navigation

// List all folders
Folder rootFolder = store.getDefaultFolder();
Folder[] allFolders = rootFolder.list("*");

for (Folder folder : allFolders) {
    System.out.println("Folder: " + folder.getFullName());
    
    // Get parent
    Folder parent = folder.getParent();
    if (parent != null) {
        System.out.println("  Parent: " + parent.getFullName());
    }
    
    // Check if it has subfolders
    if ((folder.getType() & Folder.HOLDS_FOLDERS) != 0) {
        Folder[] subfolders = folder.list();
        for (Folder subfolder : subfolders) {
            System.out.println("  Subfolder: " + subfolder.getName());
        }
    }
}

// List only subscribed folders
Folder[] subscribedFolders = rootFolder.listSubscribed("*");
for (Folder folder : subscribedFolders) {
    System.out.println("Subscribed: " + folder.getFullName());
}

// Pattern matching for folder listing
Folder[] inboxFolders = rootFolder.list("INBOX*");
Folder[] sentFolders = rootFolder.list("Sent*");

Message Operations within Folders

Moving and Copying Messages

// Open source and destination folders
Folder inbox = store.getFolder("INBOX");
Folder archive = store.getFolder("Archive");

inbox.open(Folder.READ_WRITE);
if (!archive.exists()) {
    archive.create(Folder.HOLDS_MESSAGES);
}

try {
    // Get messages to move
    Message[] messages = inbox.getMessages();
    Message[] oldMessages = Arrays.stream(messages)
        .filter(msg -> {
            try {
                Date sentDate = msg.getSentDate();
                if (sentDate != null) {
                    long daysDiff = (System.currentTimeMillis() - sentDate.getTime()) / (1000 * 60 * 60 * 24);
                    return daysDiff > 30; // Older than 30 days
                }
                return false;
            } catch (MessagingException e) {
                return false;
            }
        })
        .toArray(Message[]::new);
    
    if (oldMessages.length > 0) {
        // Copy messages to archive
        archive.appendMessages(oldMessages);
        
        // Mark original messages as deleted
        for (Message msg : oldMessages) {
            msg.setFlag(Flags.Flag.DELETED, true);
        }
        
        // Expunge to actually remove deleted messages
        inbox.expunge();
        
        System.out.println("Moved " + oldMessages.length + " messages to archive");
    }
    
} finally {
    inbox.close(false);
}

Message Fetching Optimization

// Use FetchProfile for efficient bulk operations
FetchProfile fetchProfile = new FetchProfile();
fetchProfile.add(FetchProfile.Item.ENVELOPE);
fetchProfile.add(FetchProfile.Item.FLAGS);
fetchProfile.add("X-mailer");

// Fetch specified attributes for all messages
Message[] messages = inbox.getMessages();
inbox.fetch(messages, fetchProfile);

// Now access is more efficient
for (Message message : messages) {
    System.out.println("From: " + Arrays.toString(message.getFrom()));
    System.out.println("Subject: " + message.getSubject());
    System.out.println("Flags: " + message.getFlags());
}

UID-Based Operations

For stores that support UIDs (like IMAP), you can use UID-based operations for more reliable message tracking.

// UID folder interface
public interface UIDFolder {
    public static final class FetchProfileItem extends FetchProfile.Item {
        public static final FetchProfileItem UID;
    }
    
    public long getUID(Message message) throws MessagingException;
    public Message getMessageByUID(long uid) throws MessagingException;
    public Message[] getMessagesByUID(long start, long end) throws MessagingException;
    public Message[] getMessagesByUID(long[] uids) throws MessagingException;
    public long getUIDValidity() throws MessagingException;
    public long getUIDNext() throws MessagingException;
}

UID Usage Example

if (inbox instanceof UIDFolder) {
    UIDFolder uidFolder = (UIDFolder) inbox;
    
    // Get message by UID (more reliable than message number)
    Message message = uidFolder.getMessageByUID(12345L);
    
    // Get UID for a message
    long uid = uidFolder.getUID(message);
    System.out.println("Message UID: " + uid);
    
    // Get messages by UID range
    Message[] messages = uidFolder.getMessagesByUID(1000L, 2000L);
    
    // Get folder UID validity (changes when folder is rebuilt)
    long uidValidity = uidFolder.getUIDValidity();
    System.out.println("UID Validity: " + uidValidity);
}

Quota Management

For stores that support quotas, you can monitor and manage storage limits.

// Quota-aware store interface
public interface QuotaAwareStore {
    public Quota[] getQuota(String quotaRoot) throws MessagingException;
    public void setQuota(Quota quota) throws MessagingException;
}

// Quota information
public class Quota {
    public static final class Resource {
        public static final Resource STORAGE;
        public static final Resource MESSAGE;
        
        public String name;
        public long usage;
        public long limit;
    }
    
    public String quotaRoot;
    public Resource[] resources;
}

Quota Usage Example

if (store instanceof QuotaAwareStore) {
    QuotaAwareStore quotaStore = (QuotaAwareStore) store;
    
    // Get quota information
    Quota[] quotas = quotaStore.getQuota("INBOX");
    for (Quota quota : quotas) {
        System.out.println("Quota root: " + quota.quotaRoot);
        for (Quota.Resource resource : quota.resources) {
            System.out.println("Resource: " + resource.name);
            System.out.println("Usage: " + resource.usage);
            System.out.println("Limit: " + resource.limit);
            if (resource.limit > 0) {
                double percentage = (double) resource.usage / resource.limit * 100;
                System.out.println("Usage: " + String.format("%.1f%%", percentage));
            }
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-jakarta-mail--jakarta-mail-api

docs

core-mail-operations.md

event-handling-system.md

index.md

internet-mail-mime.md

message-search-filtering.md

store-folder-management.md

utility-classes-streams.md

tile.json