or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-mail-operations.mdevent-handling-system.mdindex.mdinternet-mail-mime.mdmessage-search-filtering.mdstore-folder-management.mdutility-classes-streams.md

store-folder-management.mddocs/

0

# Store and Folder Management

1

2

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

3

4

## Store Operations

5

6

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

7

8

```java { .api }

9

public abstract class Store extends Service {

10

// Folder access

11

public abstract Folder getDefaultFolder() throws MessagingException;

12

public abstract Folder getFolder(String name) throws MessagingException;

13

public abstract Folder getFolder(URLName url) throws MessagingException;

14

15

// Event handling

16

public void addStoreListener(StoreListener l);

17

public void removeStoreListener(StoreListener l);

18

19

// Store information

20

public Folder[] getPersonalNamespaces() throws MessagingException;

21

public Folder[] getUserNamespaces(String user) throws MessagingException;

22

public Folder[] getSharedNamespaces() throws MessagingException;

23

}

24

```

25

26

### Store Usage Example

27

28

```java

29

import jakarta.mail.*;

30

import java.util.Properties;

31

32

// Configure properties for IMAP store

33

Properties props = new Properties();

34

props.put("mail.store.protocol", "imaps");

35

props.put("mail.imaps.host", "imap.gmail.com");

36

props.put("mail.imaps.port", "993");

37

props.put("mail.imaps.ssl.enable", "true");

38

39

Session session = Session.getInstance(props);

40

41

// Connect to store

42

Store store = session.getStore("imaps");

43

store.connect("imap.gmail.com", "username@gmail.com", "password");

44

45

try {

46

// Get default folder (usually root)

47

Folder defaultFolder = store.getDefaultFolder();

48

System.out.println("Default folder: " + defaultFolder.getFullName());

49

50

// Get inbox

51

Folder inbox = store.getFolder("INBOX");

52

53

// List all folders

54

Folder[] folders = defaultFolder.list("*");

55

for (Folder folder : folders) {

56

System.out.println("Folder: " + folder.getFullName());

57

}

58

} finally {

59

store.close();

60

}

61

```

62

63

## Folder Operations

64

65

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

66

67

```java { .api }

68

public abstract class Folder implements AutoCloseable {

69

// Folder constants

70

public static final int HOLDS_MESSAGES = 0x01;

71

public static final int HOLDS_FOLDERS = 0x02;

72

public static final int READ_ONLY = 1;

73

public static final int READ_WRITE = 2;

74

75

// Basic folder properties

76

public abstract String getName();

77

public abstract String getFullName();

78

public abstract Folder getParent() throws MessagingException;

79

public abstract int getType() throws MessagingException;

80

public abstract boolean exists() throws MessagingException;

81

82

// Folder operations

83

public abstract boolean create(int type) throws MessagingException;

84

public abstract boolean delete(boolean recurse) throws MessagingException;

85

public abstract boolean renameTo(Folder f) throws MessagingException;

86

87

// Folder access

88

public abstract void open(int mode) throws MessagingException;

89

public abstract void close(boolean expunge) throws MessagingException;

90

public abstract boolean isOpen();

91

public int getMode();

92

93

// Message access

94

public abstract int getMessageCount() throws MessagingException;

95

public abstract Message getMessage(int msgnum) throws MessagingException;

96

public abstract Message[] getMessages() throws MessagingException;

97

public abstract Message[] getMessages(int start, int end) throws MessagingException;

98

public abstract Message[] getMessages(int[] msgnums) throws MessagingException;

99

100

// New/unread message counts

101

public int getNewMessageCount() throws MessagingException;

102

public int getUnreadMessageCount() throws MessagingException;

103

public int getDeletedMessageCount() throws MessagingException;

104

105

// Message operations

106

public abstract void appendMessages(Message[] msgs) throws MessagingException;

107

public abstract Message[] expunge() throws MessagingException;

108

public abstract Message[] search(SearchTerm term) throws MessagingException;

109

public abstract Message[] search(SearchTerm term, Message[] msgs) throws MessagingException;

110

111

// Folder hierarchy

112

public abstract Folder[] list() throws MessagingException;

113

public abstract Folder[] list(String pattern) throws MessagingException;

114

public abstract Folder[] listSubscribed() throws MessagingException;

115

public abstract Folder[] listSubscribed(String pattern) throws MessagingException;

116

117

// Subscription management

118

public abstract boolean isSubscribed() throws MessagingException;

119

public abstract void setSubscribed(boolean subscribe) throws MessagingException;

120

121

// Event handling

122

public void addConnectionListener(ConnectionListener l);

123

public void removeConnectionListener(ConnectionListener l);

124

public void addFolderListener(FolderListener l);

125

public void removeFolderListener(FolderListener l);

126

public void addMessageChangedListener(MessageChangedListener l);

127

public void removeMessageChangedListener(MessageChangedListener l);

128

public void addMessageCountListener(MessageCountListener l);

129

public void removeMessageCountListener(MessageCountListener l);

130

131

// Store reference

132

public Store getStore();

133

134

// String representation

135

public String toString();

136

}

137

```

138

139

### Folder Usage Example

140

141

```java

142

import jakarta.mail.*;

143

import jakarta.mail.search.*;

144

145

// Open inbox for reading

146

Folder inbox = store.getFolder("INBOX");

147

inbox.open(Folder.READ_ONLY);

148

149

try {

150

// Get folder information

151

System.out.println("Folder name: " + inbox.getName());

152

System.out.println("Full name: " + inbox.getFullName());

153

System.out.println("Message count: " + inbox.getMessageCount());

154

System.out.println("New messages: " + inbox.getNewMessageCount());

155

System.out.println("Unread messages: " + inbox.getUnreadMessageCount());

156

157

// Check folder capabilities

158

if ((inbox.getType() & Folder.HOLDS_MESSAGES) != 0) {

159

System.out.println("Folder can hold messages");

160

}

161

if ((inbox.getType() & Folder.HOLDS_FOLDERS) != 0) {

162

System.out.println("Folder can hold subfolders");

163

}

164

165

// Get all messages

166

Message[] messages = inbox.getMessages();

167

168

// Get recent messages only

169

Message[] recentMessages = inbox.search(new FlagTerm(new Flags(Flags.Flag.RECENT), true));

170

171

// Get messages from specific range

172

if (messages.length > 10) {

173

Message[] lastTen = inbox.getMessages(messages.length - 9, messages.length);

174

}

175

176

} finally {

177

inbox.close(false); // Don't expunge on close

178

}

179

```

180

181

## Folder Management Operations

182

183

### Creating and Managing Folders

184

185

```java

186

// Create new folder

187

Folder newFolder = store.getFolder("Archive");

188

if (!newFolder.exists()) {

189

boolean created = newFolder.create(Folder.HOLDS_MESSAGES);

190

if (created) {

191

System.out.println("Folder created successfully");

192

}

193

}

194

195

// Create folder hierarchy

196

Folder projectFolder = store.getFolder("Projects");

197

if (!projectFolder.exists()) {

198

projectFolder.create(Folder.HOLDS_FOLDERS);

199

}

200

201

Folder subFolder = store.getFolder("Projects/Project1");

202

if (!subFolder.exists()) {

203

subFolder.create(Folder.HOLDS_MESSAGES);

204

}

205

206

// Rename folder

207

Folder oldFolder = store.getFolder("OldName");

208

Folder newFolderName = store.getFolder("NewName");

209

if (oldFolder.exists()) {

210

boolean renamed = oldFolder.renameTo(newFolderName);

211

if (renamed) {

212

System.out.println("Folder renamed successfully");

213

}

214

}

215

216

// Delete folder

217

Folder folderToDelete = store.getFolder("Temporary");

218

if (folderToDelete.exists()) {

219

// Close if open

220

if (folderToDelete.isOpen()) {

221

folderToDelete.close(false);

222

}

223

224

boolean deleted = folderToDelete.delete(false); // Don't delete recursively

225

if (deleted) {

226

System.out.println("Folder deleted successfully");

227

}

228

}

229

```

230

231

### Folder Hierarchy Navigation

232

233

```java

234

// List all folders

235

Folder rootFolder = store.getDefaultFolder();

236

Folder[] allFolders = rootFolder.list("*");

237

238

for (Folder folder : allFolders) {

239

System.out.println("Folder: " + folder.getFullName());

240

241

// Get parent

242

Folder parent = folder.getParent();

243

if (parent != null) {

244

System.out.println(" Parent: " + parent.getFullName());

245

}

246

247

// Check if it has subfolders

248

if ((folder.getType() & Folder.HOLDS_FOLDERS) != 0) {

249

Folder[] subfolders = folder.list();

250

for (Folder subfolder : subfolders) {

251

System.out.println(" Subfolder: " + subfolder.getName());

252

}

253

}

254

}

255

256

// List only subscribed folders

257

Folder[] subscribedFolders = rootFolder.listSubscribed("*");

258

for (Folder folder : subscribedFolders) {

259

System.out.println("Subscribed: " + folder.getFullName());

260

}

261

262

// Pattern matching for folder listing

263

Folder[] inboxFolders = rootFolder.list("INBOX*");

264

Folder[] sentFolders = rootFolder.list("Sent*");

265

```

266

267

## Message Operations within Folders

268

269

### Moving and Copying Messages

270

271

```java

272

// Open source and destination folders

273

Folder inbox = store.getFolder("INBOX");

274

Folder archive = store.getFolder("Archive");

275

276

inbox.open(Folder.READ_WRITE);

277

if (!archive.exists()) {

278

archive.create(Folder.HOLDS_MESSAGES);

279

}

280

281

try {

282

// Get messages to move

283

Message[] messages = inbox.getMessages();

284

Message[] oldMessages = Arrays.stream(messages)

285

.filter(msg -> {

286

try {

287

Date sentDate = msg.getSentDate();

288

if (sentDate != null) {

289

long daysDiff = (System.currentTimeMillis() - sentDate.getTime()) / (1000 * 60 * 60 * 24);

290

return daysDiff > 30; // Older than 30 days

291

}

292

return false;

293

} catch (MessagingException e) {

294

return false;

295

}

296

})

297

.toArray(Message[]::new);

298

299

if (oldMessages.length > 0) {

300

// Copy messages to archive

301

archive.appendMessages(oldMessages);

302

303

// Mark original messages as deleted

304

for (Message msg : oldMessages) {

305

msg.setFlag(Flags.Flag.DELETED, true);

306

}

307

308

// Expunge to actually remove deleted messages

309

inbox.expunge();

310

311

System.out.println("Moved " + oldMessages.length + " messages to archive");

312

}

313

314

} finally {

315

inbox.close(false);

316

}

317

```

318

319

### Message Fetching Optimization

320

321

```java

322

// Use FetchProfile for efficient bulk operations

323

FetchProfile fetchProfile = new FetchProfile();

324

fetchProfile.add(FetchProfile.Item.ENVELOPE);

325

fetchProfile.add(FetchProfile.Item.FLAGS);

326

fetchProfile.add("X-mailer");

327

328

// Fetch specified attributes for all messages

329

Message[] messages = inbox.getMessages();

330

inbox.fetch(messages, fetchProfile);

331

332

// Now access is more efficient

333

for (Message message : messages) {

334

System.out.println("From: " + Arrays.toString(message.getFrom()));

335

System.out.println("Subject: " + message.getSubject());

336

System.out.println("Flags: " + message.getFlags());

337

}

338

```

339

340

## UID-Based Operations

341

342

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

343

344

```java { .api }

345

// UID folder interface

346

public interface UIDFolder {

347

public static final class FetchProfileItem extends FetchProfile.Item {

348

public static final FetchProfileItem UID;

349

}

350

351

public long getUID(Message message) throws MessagingException;

352

public Message getMessageByUID(long uid) throws MessagingException;

353

public Message[] getMessagesByUID(long start, long end) throws MessagingException;

354

public Message[] getMessagesByUID(long[] uids) throws MessagingException;

355

public long getUIDValidity() throws MessagingException;

356

public long getUIDNext() throws MessagingException;

357

}

358

```

359

360

### UID Usage Example

361

362

```java

363

if (inbox instanceof UIDFolder) {

364

UIDFolder uidFolder = (UIDFolder) inbox;

365

366

// Get message by UID (more reliable than message number)

367

Message message = uidFolder.getMessageByUID(12345L);

368

369

// Get UID for a message

370

long uid = uidFolder.getUID(message);

371

System.out.println("Message UID: " + uid);

372

373

// Get messages by UID range

374

Message[] messages = uidFolder.getMessagesByUID(1000L, 2000L);

375

376

// Get folder UID validity (changes when folder is rebuilt)

377

long uidValidity = uidFolder.getUIDValidity();

378

System.out.println("UID Validity: " + uidValidity);

379

}

380

```

381

382

## Quota Management

383

384

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

385

386

```java { .api }

387

// Quota-aware store interface

388

public interface QuotaAwareStore {

389

public Quota[] getQuota(String quotaRoot) throws MessagingException;

390

public void setQuota(Quota quota) throws MessagingException;

391

}

392

393

// Quota information

394

public class Quota {

395

public static final class Resource {

396

public static final Resource STORAGE;

397

public static final Resource MESSAGE;

398

399

public String name;

400

public long usage;

401

public long limit;

402

}

403

404

public String quotaRoot;

405

public Resource[] resources;

406

}

407

```

408

409

### Quota Usage Example

410

411

```java

412

if (store instanceof QuotaAwareStore) {

413

QuotaAwareStore quotaStore = (QuotaAwareStore) store;

414

415

// Get quota information

416

Quota[] quotas = quotaStore.getQuota("INBOX");

417

for (Quota quota : quotas) {

418

System.out.println("Quota root: " + quota.quotaRoot);

419

for (Quota.Resource resource : quota.resources) {

420

System.out.println("Resource: " + resource.name);

421

System.out.println("Usage: " + resource.usage);

422

System.out.println("Limit: " + resource.limit);

423

if (resource.limit > 0) {

424

double percentage = (double) resource.usage / resource.limit * 100;

425

System.out.println("Usage: " + String.format("%.1f%%", percentage));

426

}

427

}

428

}

429

}

430

```